有没有办法限制 C# 中嵌套类的实例化?我想防止嵌套类从嵌套类以外的任何其他类实例化,但允许从其他代码完全访问嵌套类。
6 回答
通常我会为您想要向其他类公开的功能创建一个接口,然后将嵌套类设为私有并实现该接口。这样嵌套类定义可以保持隐藏:
public class Outer
{
private class Nested : IFace
{
public Nested(...)
{
}
//interface member implementations...
}
public IFace GetNested()
{
return new Nested();
}
}
简而言之,不,你不能那样做。有一个可访问性修饰符“public”,意思是“我内部或外部的任何东西都可以访问”,还有一个可访问性修饰符“private”,意思是“我内部的任何东西都可以访问”。没有修饰符意味着“可以访问我外面的东西,但不能访问它之外的任何东西”,这就是您需要将构造函数标记为的内容。这根本不是类型系统的设计者认为有用的概念。
你能描述一下为什么你想要这种疯狂的可访问性吗?也许有更好的方法来得到你想要的。
如果您需要满足以下条件之一:
- 您希望嵌套类被密封,
- 您不想将所有嵌套类的方法签名复制到Lee 的答案中的接口,
我找到了一个类似于ak99372 发布的解决方案,但没有使用静态初始化程序:
public class Outer
{
private interface IPrivateFactory<T>
{
T CreateInstance();
}
public sealed class Nested
{
private Nested() {
// private constructor, accessible only to the class Factory.
}
public class Factory : IPrivateFactory<Nested>
{
Nested IPrivateFactory<Nested>.CreateInstance() { return new Nested(); }
}
}
public Nested GetNested() {
// We couldn't write these lines outside of the `Outer` class.
IPrivateFactory<Nested> factory = new Nested.Factory();
return factory.CreateInstance();
}
}
这个想法是Nested
类的构造函数只能Factory
被嵌套到更深一层的类访问。该类从私有接口Factory
显式实现该方法,因此只有看得见的人才能调用并获取.CreateInstance
IPrivateFactory
IPrivateFactory
CreateInstance
Nested
类外的代码Outer
不能在Nested
不询问的情况下自由创建 的实例Outer.GetNested()
,因为
Outer.Nested
的构造函数是私有的,所以他们不能直接调用它Outer.Nested.Factory
可以实例化,但不能强制转换为IPrivateFactory
,所以CreateInstance()
不能调用它的方法。
请注意,我不建议在生产代码中大量使用该模式,但我发现在极少数情况下袖手旁观很有用。
由于 C# 语法中没有任何内容,因此您必须在它们之间实现类似“合同”之类的东西。您可以利用嵌套类可以访问其父类的私有字段这一事实:
public class ParentClass
{
private static Func<FriendClass> _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<Arg1,Arg2,FriendClass> _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 */);
}
请注意,您可以从嵌套访问外部的私有成员。