我们是否应该始终在类中包含默认构造函数?

Moo*_*oon 67 .net c# clr default-constructor

我被同事问过这个问题,我们是否应该在类中包含默认构造函数?如果是这样,为什么?如果不是,为什么不呢?

public class Foo {

    Foo() { }

    Foo(int x, int y) {
        ...
    } 

}
Run Code Online (Sandbox Code Playgroud)

我也有兴趣从专家那里了解一下.

Sco*_*man 112

您必须记住,如果您不提供重载的构造函数,编译器将为您生成默认构造函数.这意味着,如果你有的话

public class Foo
{ 
} 
Run Code Online (Sandbox Code Playgroud)

编译器将生成如下:

public class Foo
{ 
    public Foo() { }  
} 
Run Code Online (Sandbox Code Playgroud)

但是,只要添加其他构造函数

public class Foo
{ 
    public Foo(int x, int y)
    { 
        // ... 
    }  
} 
Run Code Online (Sandbox Code Playgroud)

编译器将不再为您自动生成默认构造函数.如果该类已经在其他代码中使用,而这些代码依赖于默认构造函数的存在Foo f = new Foo();,那么该代码现在将会中断.

如果您不希望某人能够在不提供数据的情况下初始化类,则应创建一个默认构造函数,该构造函数private将明确表示您正在阻止构造没有输入数据的实例.

但是,有时需要提供默认构造函数(无论是公共构造函数还是私有构造函数).如前所述,某些类型的序列化需要默认构造函数.有时候类有多个参数化构造函数,但也需要"低级"初始化,在这种情况下,可以使用从参数化构造函数链接的私有默认构造函数.

public class Foo
{
   private Foo()
   {
      // do some low level initialization here
   }

   public Foo(int x, int y)
      : this()
   {
      // ...
   }

   public Foo(int x, int y, int z)
      : this()
   {
      // ...
   }
}
Run Code Online (Sandbox Code Playgroud)

  • +1这个.创建空的默认构造函数令人讨厌IMO,像ReSharper这样的工具只是将其标记为死代码. (2认同)

Ric*_*lay 19

有些东西(比如序列化)需要一个默认的构造函数.但是,除此之外,只有在有意义的情况下才应添加默认构造函数.

例如,如果构造后的Foo.XFoo.Y属性是不可变的,那么默认构造函数就没有意义.即使它用于'空'Foo,静态Empty存取器也会更容易被发现.

  • 序列化不需要默认构造函数.如果你有一个你想要可序列化的类,默认构造函数是没有意义的,那么实现`ISerializable`,并添加一个构造函数(`private` if sealed,`protected`否则)签名`ClassName(SerializationInfo) info,StreamingContext context)`镜像`ISerializable.GetObjectData`的实现. (3认同)

Dan*_*Tao 12

我会说没有,绝对不是永远.假设你有一个带有一些readonly字段的类,必须初始化为某个值,并且没有合理的默认值(或者你不希望有)?在这种情况下,我不认为无参数构造函数是有意义的.

  • 完全同意.应始终在有效状态下实例化类.如果你有一个默认的ctor并在构造后设置属性,那么实例何时有效?设置一些属性后?设置全部?谁知道. (4认同)

Jon*_*nna 5

如果有这样的对象是有意义的,那么拥有默认构造函数是个好主意.

如果你从这样的构造函数生成一个不在有效状态的对象,那么它唯一能做的就是引入一个bug.