F#从C#继承的类访问受保护的字段

时间:2017-07-26 07:29:21

标签: c# f#

我在C#中有一个类,如下所示:

class A {
    protected SomeClass Field;
}

class B: A {}

并在F#中使用以下代码:

type C() =
    inherit B()

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

我想访问受保护的字段Field。我知道我可以通过简单类型base.somethingwhich is also answered here)访问B类中的受保护字段,但是当我输入base.Field来访问类 A 中的受保护字段时得到struct or class field is not accessible from this code location的错误,因为在类A(?)中声明了Field。 我的问题是,是否有可能访问它?

2 个答案:

答案 0 :(得分:2)

我找到了解决问题的方法。 像这样的代码不正确:

type C() =
    inherit B()

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

但是这样的代码可以正常工作:

type C() =
    inherit B()

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

答案 1 :(得分:2)

您的存根解决方法之所以有效,是因为您尝试访问let-bound函数d正文中的受保护字段。这些函数被移出它们定义的上下文之外并被编译成FSharpFunc类型的子类型。也就是说,你在编译的F#代码(简化图片)中得到类似的东西:

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);
    }
}

这意味着您尝试访问受保护字段的代码块不再属于类C,而protected修饰符会阻止访问。

如果你将值绑定在d之外,你可以得到类似的结果:

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

并且不再在类C之外发生受保护的访问。