Ответ 1
Из спецификации F # 3.0: скомпилированная форма CLI всех непубличных объектов внутренняя.
Я всегда предполагал, что ключевые слова управления доступом в F # (public
, private
, internal
) работают так же, как и на С#. В самом деле, из документации MSDN Контроль доступа (F #):
- общедоступный указывает, что к объекту могут быть доступны все вызывающие абоненты.
- внутренний указывает, что к объекту можно получить доступ только из той же сборки.
- 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
Я собрал немного кода на С#, чтобы убедиться, что я не воображаю ничего.
тестовый код С#, и все компилируется.
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 с одинаковыми результатами.
Вопрос. Каково фактическое ожидаемое поведение по дизайну? Это ошибка? Или я делаю что-то неправильно?
Предложение. Если это предполагаемое поведение, возможно, было бы неплохо четко указать это в документации где-нибудь?
Из спецификации F # 3.0: скомпилированная форма CLI всех непубличных объектов внутренняя.