【问题标题】:What's the difference between a public constructor in an internal class and an internal constructor?内部类中的公共构造函数和内部构造函数有什么区别?
【发布时间】:2011-04-16 09:34:53
【问题描述】:

我有一个内部类,内部构造函数不允许在泛型集合中使用它,所以我将其更改为公共。如果您在内部类中有一个公共构造函数,那么可访问性是什么?与拥有一个内部构造函数有什么不同?

【问题讨论】:

    标签: c#


    【解决方案1】:

    两者本质上是一样的。我看到的区分它们的一个论点是,使您的构造函数 internal 确保该类型只会被当前程序集中的类型实例化,即使后来决定该类型本身应该是 public 而不是internal。换句话说,您可以决定更改 type 的可见性而不解除对其实例化的限制。

    使构造函数public 具有相反的效果(显然),如果您希望可以在任何可见的地方实例化类型,这可能是明智的。

    另外,正如您已经指出的,一个小的区别是,如果构造函数的internal,则该类型不能用作具有@987654326 的泛型类型的泛型类型参数@约束,因为这个约束要求构造函数是public

    【讨论】:

    • 但是如果将constructor设置为public,class设置为internal,这不是矛盾吗? public:访问不受限制。 internal:访问仅限于当前程序集。所以构造函数应该比类更可见。这是不可能的!
    • @Cirelli94,cstor 上的公共访问器并不意味着它在类范围之外是公共的。术语“公共”、“私人”等并不规定绝对可见性(例如:“公共”!=“无论如何从 assm 外部可见”)。相反,范围是嵌套的。例如:可以在私有类中具有公共方法,在私有类中具有公共类,等等。当然 - 从功能上讲,有一些重叠。但是,从声明上讲,这些重叠赋予了不同的规则(例如:可能会说私有类 A 中包含的公共类 B 意味着 B 应该对 A 具有最大可见性。B 不知道也不关心那是什么)。
    【解决方案2】:

    如果您从公共函数返回该类的对象,外部代码仍然可以使用具有内部构造函数的公共类。

    然后外部代码可以访问该对象,但仍无法创建新对象。

    Assembly 1:
    
    public class Exclusive
    {
      internal Exclusive() {}
      public void DoSomething() {}
    }
    
    public class Factory
    {
      public Exclusive GetExclusive() { return new Exclusive(); }
    }
    
    Assembly 2:
    
    Factory MyFactory = new Factory();
    Exclusive MyExclusive = MyFactory.GetExclusive(); // Object is created in Assembly 1
    MyExclusive.DoSomething();
    
    Exclusive MyExclusive = new Exclusive(); // Error: constructor is internal
    

    而内部类根本不能在程序集之外使用:

    Assembly 1:
    
    internal class Exclusive
    {
      public Exclusive() {}
      public void DoSomething() {}
    }
    
    public class Factory
    {
      public Exclusive GetExclusive() { return new Exclusive(); }
    }
    
    Assembly 2:
    
    Factory MyFactory = new Factory();
    Exclusive MyExclusive = MyFactory.GetExclusive(); // Error: class Exclusive not found
    

    【讨论】:

      【解决方案3】:

      就可见性而言,具有内部类型的内部或公共构造函数将是等效的。

      【讨论】:

        【解决方案4】:

        当您不希望客户端创建实例时,内部构造函数很好。如果您想控制应该如何创建实例,您通常会想要这样做。您必须提供一个工厂来在同一程序集中的另一个类中生成该类,以便在内部生成实例,然后作为属性公开.

        【讨论】:

        • 我认为 OP 已经知道这一点。他的类型是internal,所以客户端甚至无法看到它,更不用说实例化它了。
        【解决方案5】:

        另一个重要区别是,要使用反射访问 internal 构造函数,您需要在对 Type.GetConstructor() 的调用中指定绑定标志 - Type.GetConstructor(Type[]) 重载只会返回公共构造函数:

        using System;
        internal class WithPublic
        {
            public WithPublic() { }
        }
        
        internal class WithInternal
        {
            internal WithInternal() { }
        }
        
        public class Program
        {
            public static void Main()
            {
                Console.WriteLine(typeof(WithPublic).GetConstructor(new Type[] { }) == null); //false
                Console.WriteLine(typeof(WithInternal).GetConstructor(new Type[] { }) == null); //true
            }
        }
        

        当您使用使用 Type.GetConstructor(Type[]) 重载的库(如 Microsoft Unity)时,这可能很重要。

        【讨论】:

          猜你喜欢
          • 2011-10-23
          • 1970-01-01
          • 2016-07-31
          • 1970-01-01
          • 2020-06-18
          • 2013-05-06
          • 1970-01-01
          • 2021-01-08
          • 1970-01-01
          相关资源
          最近更新 更多