F#实际上将私有成员编译为IL中的内部成员.错误?

Phi*_* P. 16 .net f#

我一直认为,在F#访问控制的关键字(public,private,internal)在,因为他们在C#中做同样的工作方式.确实从MSDN文档访问控制(F#):

  • public表示所有呼叫者都可以访问该实体.
  • internal表示只能从同一个程序集访问该实体.
  • private表示只能从封闭类型或模块访问实体.

这似乎与我的假设非常一致,并且在SO提供的主题上也有多个答案.

但是,当我使用Reflector调入已编译的代码时,我发现所有声明为private的成员实际上都被编译为内部(程序集可见性),这与文档不匹配.

为了避免任何疑问,我创建了一个小测试来确认这一点.

F#代码:

// Make internals visible to other assemblies
[<assembly:InternalsVisibleTo("MyCSharpAssembly")>]


// OK. Expect: "internal static class PrivateModule" in C#
module private PrivateModule =

    // FAIL. Expect: "private static void privateStaticMethod()" in C#
    let private privateStaticMethod() = ignore()

// OK. Expect: "internal class InternalClass" in C#
type private InternalClass() =

    // FAIL. Expect: "private int privateInstanceField" in C#
    let privateInstanceField = 0

    // FAIL. Expect: "private static int privateStaticField" in C#
    static let privateStaticField = 0

    // FAIL. Expect: "private int privateInstanceMethod()" in C#
    let privateInstanceMethod() = privateInstanceField

    // FAIL. Expect: "private in PrivateInstanceMember()" in C#
    member private this.PrivateInstanceMember() = privateInstanceField

    // OK. Expect: "internal int InternalInstanceMember" in C#
    member internal this.InternalInstanceMember() = privateStaticField
Run Code Online (Sandbox Code Playgroud)

我已经整理了一些C#代码,以确保我没有想象的东西.

C#测试代码,一切都编译好了.

public class TestVisibility
{
    // This is a demo to verify that the members are indeed
    // internal (assembly) and can be accessed from C# if the
    // F# assembly is compiled with [<assembly:InternalsVisibleTo("C# assembly")>]
    public void Run()
    {
        // All of these compile.
        PrivateModule.privateStaticMethod();

        InternalClass x = new InternalClass();

        int a = InternalClass.privateStaticField;
        var b = x.InternalInstanceMember();
        var c = x.PrivateInstanceMember();
        var d = x.privateInstanceField;
        var f = x.privateInstanceMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用VS2012,针对.NET 4.0,所有设置都是默认设置.尝试调试和释放模式具有相同的结果.

问题:根据设计,实际预期行为是什么?这是一个错误吗?或者我做错了什么?

建议:如果这是预期的行为,或许在文档中明确提到这个可能是个好主意?

小智 13

F#3.0规范:所有非公共实体的CLI编译形式是内部的.

  • 嗯,这看起来像一个spec bug,如上所述,它说内部字段可以由InternalsVisibleTo中列出的程序集访问,但私有字段只能由封闭类型访问.在CLI处编译所有内容以使这些语句不再成立. (2认同)