嵌套类构造函数的可见性

有没有办法限制C#中嵌套类的实例化? 我想防止嵌套类从除嵌套类之外的任何其他类实例化,但允许从其他代码完全访问嵌套类。

通常我会为要向其他类公开的function创建一个接口,然后使嵌套类成为私有并实现该接口。 这样嵌套的类定义可以保持隐藏状态:

 public class Outer { private class Nested : IFace { public Nested(...) { } //interface member implementations... } public IFace GetNested() { return new Nested(); } } 

总之,不,你不能那样做。 有一个accessibity修饰符“public”,意思是“可以通过我内部或我之外的任何东西访问”,并且有一个可访问性修饰符“private”,意思是“可以通过我内部的任何东西访问”。 没有修饰符意味着“对我外面的东西可以访问但不能访问它之外的任何东西”,这就是你需要将构造函数标记为。 这根本不是类型系统设计者认为有用的概念。

你能描述为什么你想要这种疯狂的可访问性吗? 也许有更好的方法来获得你想要的东西。

如果您需要满足以下要求之一:

  • 您希望密封嵌套类,
  • 您不希望将所有嵌套类的方法签名复制到Lee的答案中的接口,

我找到了类似于ak99372发布的解决方案,但没有使用静态初始化器:

 public class Outer { private interface IPrivateFactory { T CreateInstance(); } public sealed class Nested { private Nested() { // private constructor, accessible only to the class Factory. } public class Factory : IPrivateFactory { Nested IPrivateFactory.CreateInstance() { return new Nested(); } } } public Nested GetNested() { // We couldn't write these lines outside of the `Outer` class. IPrivateFactory factory = new Nested.Factory(); return factory.CreateInstance(); } } 

我们的想法是,只有Factory类可以访问Nested类的构造函数,而Factory类的嵌套级别更深。 Factory类从私有接口IPrivateFactory显式实现方法CreateInstance ,这样只有那些可以看到IPrivateFactory才能调用CreateInstance并获得一个新的Nested实例。

Outer类之外的代码无法在不询问Outer.GetNested()情况下自由创建Nested实例,因为

  1. Outer.Nested的构造函数是Outer.Nested的,因此无法直接调用它
  2. Outer.Nested.Factory可以实例化,但不能转换为IPrivateFactory ,因此无法调用其CreateInstance()方法。

请注意,我不建议在生产代码中大量使用该模式,但这是一个技巧,我发现在极少数情况下可以使用它。

由于C#语法中没有任何内容,您必须在它们之间实现类似“契约”的内容。 您可以利用嵌套类可以访问其父级的私有字段这一事实:

 public class ParentClass { private static Func _friendContract; public class FriendClass { static FriendClass() { _friendContract= () => new FriendClass(); } private FriendClass() { } } ///Usage public FriendClass MethodUse() { var fInstance = _friendContract(); //fInstance.DoSomething(); return fInstance; } } 

当然,您可以调整合约以处理不同的参数

  private static Func _friendContract; 

对于Joshua Smith提出的答案,我发现有必要强制运行FriendClass的静态构造函数,通过从ParentClass的静态构造函数调用FriendClass上的空静态Initalize()方法来实现。

 public class Outer { public class Nested { readonly Outer Outer; public Nested(Outer outer /* , parameters */) { Outer = outer; // implementation } // implementation } public Nested GetNested(/* parameters */) => new Nested(this /* , parameters */); } 

请注意,您可以从嵌套中访问Outer的私有成员。

更新:答案不正确,请参阅评论

内部修饰符是您正在寻找的:

 public class OuterClass { public class NestedClass { internal NestedClass() { } } } 

NestedClass对所有人都可见,但它的构造函数只对OuterClass可用。