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();
    }
}