【问题标题】:Allow access to but prevent instantiation of a nested class by external classes允许访问但阻止外部类实例化嵌套类
【发布时间】:2012-10-19 13:09:30
【问题描述】:

我希望定义一个容器类和外部类可以访问的嵌套类,但我想控制嵌套类的实例化,这样只有容器类的实例才能创建嵌套类的新实例.

接下来的代码应该可以证明这一点:

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 必须是公开的,以便External 可以访问它。我尝试使Nested 的构造函数受保护,但这会阻止Container 创建实例,因为Container 不是Nested 的基类。我可以将Nested 的构造函数设置为internal,但我希望防止所有外部类(包括同一程序集中的类)访问构造函数。有没有办法做到这一点?

如果这不能通过访问修饰符实现,我想知道我是否可以在Nested() 中抛出异常。但是,我不知道如何测试调用 new Nested() 的上下文。

【问题讨论】:

    标签: c# encapsulation inner-classes nested-class


    【解决方案1】:

    通过接口进行抽象怎么样?

    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
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      以这种方式声明类是不可能的。我认为对您来说最好的方法是将类声明为私有并通过公共接口公开它:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 2014-10-30
        • 1970-01-01
        • 2017-01-25
        相关资源
        最近更新 更多