我一直认为F#(public
,private
,internal
中的访问控制关键字的工作方式与它们在C#中的工作方式相同。确实来自MSDN文档Access Control (F#):
- public 表示所有呼叫者都可以访问该实体。
- 内部表示只能从同一个程序集访问该实体。
- 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,所有设置都是默认设置。尝试使用相同的结果调试和释放模式。
问题:根据设计,实际预期行为是什么?这是一个错误吗?或者我做错了什么?
建议:如果这是预期的行为,或许在文档中明确提到这个可能是个好主意?