C# 允许访问但防止外部类实例化嵌套类
我希望定义一个可供容器类和外部类访问的嵌套类,但我希望控制嵌套类的实例化,以便只有容器类的实例可以创建嵌套类的新实例 下面的代码应该有希望证明这一点:C# 允许访问但防止外部类实例化嵌套类,c#,encapsulation,inner-classes,nested-class,C#,Encapsulation,Inner Classes,Nested Class,我希望定义一个可供容器类和外部类访问的嵌套类,但我希望控制嵌套类的实例化,以便只有容器类的实例可以创建嵌套类的新实例 下面的代码应该有希望证明这一点: public class Container { public class Nested { public Nested() { } } public Nested CreateNested() { return new Nested(); // Allow }
public class Container
{
public class Nested
{
public Nested() { }
}
public Nested CreateNested()
{
return new Nested(); // Allow
}
}
class External
{
static void Main(string[] args)
{
Container containerObj = new Container();
Container.Nested nestedObj;
nestedObj = new Container.Nested(); // Prevent
nestedObj = containerObj.CreateNested(); // Allow
}
}
嵌套的
必须是公共的,才能被外部
访问。我试图使嵌套的
的构造函数受到保护,但是这会阻止容器
创建实例,因为容器
不是嵌套的
的基类。我可以将Nested
的构造函数设置为internal
,但我希望阻止所有外部类(包括同一程序集中的类)访问构造函数。有办法做到这一点吗
如果这不能通过访问修饰符实现,我想知道是否可以在
Nested()
中抛出异常。但是,我不知道如何测试调用new Nested()
的上下文。如何通过接口进行抽象
public class Container
{
public interface INested
{
/* members here */
}
private class Nested : INested
{
public Nested() { }
}
public INested CreateNested()
{
return new Nested(); // Allow
}
}
class External
{
static void Main(string[] args)
{
Container containerObj = new Container();
Container.INested nestedObj;
nestedObj = new Container.Nested(); // Prevent
nestedObj = containerObj.CreateNested(); // Allow
}
}
您还可以对抽象基类执行相同的操作:
public class Container
{
public abstract class Nested { }
private class NestedImpl : Nested { }
public Nested CreateNested()
{
return new NestedImpl(); // Allow
}
}
class External
{
static void Main(string[] args)
{
Container containerObj = new Container();
Container.Nested nestedObj;
nestedObj = new Container.Nested(); // Prevent
nestedObj = containerObj.CreateNested(); // Allow
}
}
以这种方式声明类是不可能的。我认为最好的方法是将类声明为私有并通过公共接口公开它:
class Program
{
static void Main(string[] args)
{
// new S.N(); does not work
var n = new S().Create();
}
}
class S
{
public interface IN
{
int MyProperty { get; set; }
}
class N : IN
{
public int MyProperty { get; set; }
public N()
{
}
}
public IN Create()
{
return new N();
}
}