【问题标题】:F# actually compiles private members as internal in IL. Bug?F# 实际上将私有成员编译为 IL 中的内部成员。漏洞?
【发布时间】:2013-09-10 20:29:04
【问题描述】:

我一直认为 F# 中的访问控制关键字(publicprivateinternal)与 C# 中的工作方式相同。确实来自 MSDN 文档Access Control (F#)

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

这似乎与我的假设非常一致,也与 SO 此处提供的主题的多个答案一致。

但是,当我用 Reflector 探查编译后的代码时,我发现所有声明为 private 的成员实际上都被编译为 internal(程序集可见性),即与文档不符。

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

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

我整理了一些 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();
    }
}

我用的是VS2012,面向.NET 4.0,所有设置都是默认的。尝试了 Debug 和 release 模式,结果相同。

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

建议:如果这是预期行为,那么在文档中的某个地方明确提及这一点可能是个好主意?

【问题讨论】:

    标签: .net f#


    【解决方案1】:

    来自F# 3.0 specification所有非公共实体的 CLI 编译形式都是内部

    【讨论】:

    • 嗯,这似乎是一个规范错误,如上所述,它说内部字段可以由 InternalsVisibleTo 中列出的程序集访问,但私有字段只能由封闭类型访问。在 CLI 中编译所有内容以调整内部结构,这些陈述不再正确。
    猜你喜欢
    • 2017-12-22
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    相关资源
    最近更新 更多