是必需的默认构造函数吗?

时间:2013-05-20 13:48:57

标签: c#

这两者有什么区别?

class Class1
{
    public int a = 1;
}

class Class2
{
    public int a;
    public Class2()
    {
        a = 1;
    }
}

如果没有,我可以跳过默认构造函数并像Class1一样初始化我的变量吗?

5 个答案:

答案 0 :(得分:8)

调用new Class1()首先将a设置为1,然后调用基类构造函数。

首先调用new Class2()调用基类构造函数,然后将a设置为1

由于您是从object派生的,因此基类构造函数不执行任何操作。在其他情况下,它可能会有所不同。

答案 1 :(得分:8)

您不会注意到代码中的差异,但不同之处在于调用和初始化事物的顺序:

  1. 运行派生类字段初始值设定项。
  2. 运行基类字段初始值设定项。
  3. 运行基类构造函数。
  4. 运行派生类构造函数。
  5. 因此,在Class1中,字段在步骤1中初始化。在Class2中,字段在步骤1中初始化为其默认值0,然后在步骤4中设置为1。

    Eric Lippert的文章系列Why do initializers run in the opposite order as constructors, part 1part 2中的更多信息。

答案 2 :(得分:3)

区别在于构造函数调用和'a'字段设置之间的顺序,正如您在IL中可以看到的每个类:

Class1

  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.1
  IL_0002:  stfld      int32 SandBox.Class1::a
  IL_0007:  ldarg.0
  IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
  IL_000d:  ret

<强>的Class2

.maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  ldarg.0
  IL_0007:  ldc.i4.1
  IL_0008:  stfld      int32 SandBox.Class2::a
  IL_000d:  ret

答案 3 :(得分:1)

您不能对每个字段或自动属性使用初始化。构造函数使您能够为这些字段和属性设置值。

应该注意的是,字段初始化是在类中的每个构造函数之前,所以编写一个默认构造函数(并且让一个类的所有其他构造函数从它继续)可能是从代码大小的角度来看,效率更高。这是一种默认构造函数可以派上用场的方式。

答案 4 :(得分:1)

在您的具体示例中,字段初始值设定项(Class1)没问题。可以说,不是的是公共领域; p我会建议:

// manually implemented property with field-initializer
private int a = 1;
public int A { get { return a;} set { a = value;} }

或:

// automatically implemented property with constructor-based initialization
public int A {get;set;}
public Class1() {
    A = 1;
}

@hvd's answer正确地说明了区别。为了说明这可以给出不同结果的具体示例,请参阅以下内容。这个示例中的主要收集消息实际上是“在使用构造函数的virtual方法时非常小心”。

先输出:

Class1: 1
Class2: 0

代码:

using System;
abstract class SomeBaseClass {
    protected abstract void Write();
    protected SomeBaseClass() {
        Console.Write(GetType().Name + ": ");
        Write();
    }
}
class Class1 : SomeBaseClass {
    protected override void Write() {
        Console.WriteLine(a);
    }
    public int a = 1;
}

class Class2 : SomeBaseClass {
    protected override void Write() {
        Console.WriteLine(a);
    }
    public int a;
    public Class2() {
        a = 1;
    }
}
static class Program {
    static void Main() {
        new Class1();
        new Class2();
    }
}