Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to use protected events in F#

Tags:

f#

Let's say we have the following C# class

public class Class1
{
    protected event EventHandler ProtectedEvent;
    protected virtual void OverrideMe() { }
}

It seems to be impossible to use the ProtectedEvent in F#.

type HelpMe() as this =
    inherit Class1()

    do
        printfn "%A" this.ProtectedEvent        

    member x.HookEvents() =
        printfn "%A" x.ProtectedEvent

    member private x.HookEvents2() =
        printfn "%A" x.ProtectedEvent 

    override x.OverrideMe() =
        printfn "%A" x.ProtectedEvent 

In this example I have attempted to call printfn on it, as there are multiple ways to hook up events in F# and I wanted to be clear that is simply the referencing of the event at all that causes the problem.

In each of the cases above the compiler complains with the following error

A protected member is called or 'base' is being used. This is only allowed in the direct implementation of members since they could escape their object scope.

I understand this error, what causes it and its purpose. Usually, the work around is to wrap the call in a private member, which works fine with methods - but that does not seem to work with events. No matter what I try, it seems to be impossible to use protected events in F# unless I resort to doing something with reflection, or make some changes to the base class (which in my case is not possible).

Note that I have also tried all possible combinations of using base, this and x.

Am I doing something wrong ?

like image 423
Ross McKinlay Avatar asked Oct 20 '22 19:10

Ross McKinlay


1 Answers

I suspect that there is something about the code that the compiler generates behind the scene when you treat the event as a first-class value that later confuses it (i.e. some hidden lambda function that makes the compiler think it cannot access the protected member). I'd say that this is a bug.

As far as I can see, you can workaround it by using add_ProtectedEvent and remove_ProtectedEvent members directly (they do not show in the auto-completion, but they are there and are accessible - they are protected, but calling them is a direct method call, which is fine):

type HelpMe() =
    inherit Class1()

    member x.HookEvents() =
        let eh = System.EventHandler(fun _ _ -> printfn "yay")
        x.add_ProtectedEvent(eh)

    override x.OverrideMe() =
        printfn "hello"

This compiled fine for me. It is a shame that you cannot use the protected event as a first-class value, but this at least lets you use it...

like image 141
Tomas Petricek Avatar answered Jan 04 '23 06:01

Tomas Petricek