用F#语言重载C#类中的方法会导致该方法不可内省?

5

我有以下的C#类:

public class Foo {
    protected virtual void Bar (){
    }
}

public class Baz : Foo {
    protected override void Bar (){
    }
}

如果我审视它们,方法Bar总是在那里:

[<EntryPoint>]
let main args =
    let methodFromFoo = typedefof<Foo>.GetMethod("Bar", BindingFlags.Instance ||| BindingFlags.NonPublic)
    if (methodFromFoo <> null) then
        Console.WriteLine ("methodFromFoo is not null")
    else
        Console.WriteLine ("methodFromFoo is null")

    let methodFromBaz = typedefof<Baz>.GetMethod("Bar", BindingFlags.Instance ||| BindingFlags.NonPublic)
    if (methodFromBaz <> null) then
        Console.WriteLine ("methodFromBaz is not null")
    else
        Console.WriteLine ("methodFromBaz is null")

结果是对于两种情况都是不是null

但是,当我使用F#类进行相同操作时,结果是不同的:

type FSharpBaz() =
    inherit Foo()
    override this.Bar () =
        Console.WriteLine ("yeh")

[<EntryPoint>]
let main args =
    let methodFromFsharp = typedefof<FSharpBaz>.GetMethod("Bar", BindingFlags.Instance ||| BindingFlags.NonPublic)
    if (methodFromFsharp <> null) then
        Console.WriteLine ("methodFromFsharp is not null")
    else
        Console.WriteLine ("methodFromFsharp is null")

但为什么?如果我的类是使用F#创建的,我不能通过反射获得方法吗?我感到非常沮丧。

1个回答

9
你看不到它的原因是因为 FSharpBaz.Bar 被编译成了 public 而不是 protected。你可以通过在 ildasm 中查看代码来验证这一点。实际上,这是完全合法的行为,并在 CLI 规范的第 8.5.3.2 节中进行了说明。

当一个类型定义了一个覆盖继承定义的虚方法时,可访问性应该与两个定义中的其中一个相同,或者覆盖定义应该允许比原始定义更多的访问权限。

至于为什么 F# 在这里使用 public,那只是成员定义的默认值。

如果没有使用访问修饰符,则默认为 public,除了类型中的 let 绑定始终是私有的(链接


1
好的,谢谢!我想我没有意识到这一点,因为在C#中,当覆盖方法时改变其可访问性是不合法的。 - knocte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接