【问题标题】:Does an empty private constructor in a nested class make any sense?嵌套类中的空私有构造函数是否有意义?
【发布时间】:2015-03-12 16:52:35
【问题描述】:

我遇到了这样一个嵌套类的源代码:

public class OuterClass
{
  // code of the outer class

  protected class NestedClass
  {
    private string myVar;

    private NestedClass() {} // <--- empty private ctor

    public NestedClass(string myVar)
    {
      this.myVar = myVar;
    } 
  }
}

创建这个空的私有构造函数的原因是什么?

我知道在实现单例时,构造函数必须是私有的,以防止其他类创建实例。但是,如果是另一个公共构造函数,所以这不是原因。

我想到的一个原因是不允许创建没有变量值的实例,该变量作为参数传递给公共构造函数,但据我所知,当除了带参数的公共构造函数之外,没有其他构造函数。对吗?

编辑:一个现在被删除的答案,提到了默认构造函数。据我所知,只有在根本没有手动编写的构造函数时才存在“隐藏”默认构造函数。这是here描述的:

这些构造函数被注入到所有不引入其他构造函数的类声明中。

因此,我的嵌套类的空构造函数不是默认构造函数,而只是一个没有参数的构造函数。我假设顶级类和嵌套类都是这种情况。

【问题讨论】:

  • 该代码无法编译。我猜你的意思是private NestedClass(){}
  • 除非您在自身内部创建NestedClass 的实例,否则私有空构造函数不适用于在类外部创建实例。
  • @MatthewWatson 你是对的
  • 我认为将默认构造函数设为私有没有任何意义,除了可以通过反射调用它。
  • @PhilippM 根据代码上下文,NestedClass 无法使用默认构造函数进行实例化。它施加的限制是:始终使用参数化构造函数,其中参数的值对于构建实例很重要。

标签: c#


【解决方案1】:

我认为这意味着只有这个类才能使用这个构造函数创建自己的实例。类中的代码是否在任何地方调用此构造函数?

【讨论】:

【解决方案2】:

如果类想要限制你调用在它上面定义的某种工厂方法来创建它,通常你会有一个私有构造函数,但是由于定义了另一个构造函数,所以情况似乎并非如此.

你可以使用反射来定位私有构造函数,一旦你得到了私有构造函数的ConstructorInfo,你就可以调用它来创建类的实例,但这将是一个非常小众的事情做!

【讨论】:

  • 感谢您的意见,但为什么要创建一个私有构造函数,仅通过反射调用它?
【解决方案3】:

如果你有一个非默认构造函数并且没有指定默认构造函数,那么 any 代码将无法访问默认构造函数,因为编译器不会创建一个。 p>

如果您有一个非默认构造函数并且还指定了一个私有默认构造函数,那么NestedClass 方法可以使用默认构造函数。您的代码没有这样做,因此没有必要提供默认构造函数(私有或其他)。

还有一个模糊的情况可以产生影响:通过提供默认的NestedClass 构造函数,您可以启用反射来访问它。

以下程序演示。

如果你运行它,它会打印“Demo.OuterClass+NestedClass”。

如果你注释掉私有默认的NestedClass构造函数并运行它,它会崩溃。

除了这种不太可能的情况,我看不出提供私有构造函数的合理理由。

using System;
using System.Reflection;

namespace Demo
{
    public class OuterClass
    {
        protected class NestedClass
        {
            private string myVar;

            private NestedClass(){} // Commenting-out this line will cause the reflection to break.

            public NestedClass(string myVar)
            {
                this.myVar = myVar;
            }
        }
    }

    public class MyDerivedClass: OuterClass
    {
        public MyDerivedClass()
        {
            Type type = typeof(NestedClass);
            var ctor = type.GetConstructor(BindingFlags.Instance|BindingFlags.NonPublic, null, Type.EmptyTypes, null);
            var nested = (NestedClass) ctor.Invoke(null);

            Console.WriteLine(nested);
        }
    }

    public static class Program
    {
        private static void Main()
        {
            var test = new MyDerivedClass();
        }
    }
}

如果你不想显式允许反射调用私有默认构造函数,那么我会说提供它确实没有意义,你应该从代码中删除它。

【讨论】:

  • 我的猜测是您是对的,我应该将其从代码中删除,但如果其他人有理由回答,我会等待,然后再接受您的回答。谢谢!
猜你喜欢
  • 2012-09-14
  • 2014-06-11
  • 2012-04-25
  • 1970-01-01
  • 2018-06-12
  • 2011-09-13
  • 1970-01-01
  • 2018-10-20
  • 2014-05-31
相关资源
最近更新 更多