在 C# 中有没有一种方法可以限制嵌套类的实例化?我想防止从任何其他类实例化嵌套类,但允许其他代码完全访问嵌套类。
在 C# 中有没有一种方法可以限制嵌套类的实例化?我想防止从任何其他类实例化嵌套类,但允许其他代码完全访问嵌套类。
通常我会为想要向其他类公开的功能创建一个接口,然后将嵌套类设置为私有并实现该接口。这样,嵌套类定义就可以保持隐藏:
public class Outer
{
private class Nested : IFace
{
public Nested(...)
{
}
//interface member implementations...
}
public IFace GetNested()
{
return new Nested();
}
}
如果您需要满足以下要求之一:
我找到了一个类似于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
类明确实现了来自私有接口 IPrivateFactory
的方法 CreateInstance
,因此只有那些可以看到 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;
使用 C# 11 的新静态抽象接口成员,您可以相当简洁地限制嵌套类的实例化:
public class Outer
{
protected interface INestedFactory<T> where T : INestedFactory<T>
{
public static abstract T CreateInstance();
}
public class SomeNested : INestedFactory<SomeNested>
{
private SomeNested() { }
static SomeNested INestedFactory<SomeNested>.CreateInstance()
{
return new SomeNested();
}
}
protected void CreateNested<T>() where T : INestedFactory<T>
{
T.CreateInstance();
}
}
对于Joshua Smith提出的答案,我发现有必要强制运行FriendClass的静态构造函数,可以通过在ParentClass的静态构造函数中调用FriendClass的空静态Inititalize()方法来实现。
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 */);
}
internal
的问题在于它仍然允许同一程序集中的其他类型访问这些成员。C# 需要的是一种 "父级" 可见性,只允许封闭嵌套类型的类型访问该类型。 - Chris Charabaruk