MNie
MNie

Reputation: 1367

F# access protected field from a C# inherited class

I have a class in C# which looks like this:

class A {
    protected SomeClass Field;
}

class B: A {}

and following code in F#:

type C() =
    inherit B()

    member this.SomeMethod() =
        let magic() = base.Field.SomeMoreMagic(someParam) //this.Field also fails
        ...

in which I want to access the protected field Field. I know that I could access protected fields from class B by simple type base.something (which is also answered here) but when I type base.Field to access protected field from class A I get an error that struct or class field is not accessible from this code location, because Field is declared in class A(?). My question is, is there some possibility to access it?

Upvotes: 1

Views: 231

Answers (2)

scrwtp
scrwtp

Reputation: 13577

The reason why your stub workaround works is because you're trying to access the protected field within the body of a let-bound function d. Such functions are moved outside of the context they're defined in and compiled into subtypes of FSharpFunc type. That is, you get something like this in the compiled F# code (simplified picture):

internal class d@11 : FSharpFunc<Unit, int>
{
    public C @this;

    internal d@11(C @this)
    {
        this.@this = @this;
    }

    public override int Invoke(Unit unitVar0)
    {
        // this would be an attempt to access the protected field 
        // if the compiler allowed it.
        return @this.Field.SomeMoreMagic();  
    }
}

public class C : B
{
    public int SomeMethod()
    {
        FSharpFunc<Unit, int> d = new d@11(this);
        return d.Invoke(null);
    }
}

Which means that the block of code where you tried to access the protected field is no longer part of class C, and protected modifier prevents access there.

Whereas if you bind the value outside of d, you get something like this:

public class C : B
{
    public int SomeMethod()
    {
        SomeClass stub = this.Field;
        FSharpFunc<Unit, int> d = new d@11(stub);
        return d.Invoke(null);
    }
}

and no protected access happens outside class C anymore.

Upvotes: 2

MNie
MNie

Reputation: 1367

I found a resolution to my problem. Code like this is incorrect:

type C() =
    inherit B()

    member this.SomeMethod() =
        let d() = base.Field.SomeMagic(someParameter) //this.Field also fails
        d()

but code like this works correctly:

type C() =
    inherit B()

    member this.SomeMethod() =
        let stub = this.Field
        let d() = stub.SomeMagic(someParameter)
        d()

Upvotes: 2

Related Questions