2011-01-05 76 views
31

如果您使用语法连锁构造函数调用:构造链接订购

public frmConfirm(): this(1) 

时被称为重载的构造函数?另外,有人可以证实,如果这个类是一个表单,在两个构造函数中都有InitializeComponent()调用会产生问题吗?

+5

@ madmik3:它确实很容易编写代码来查看会发生什么。那么问题是,是否确保*在所有情况下都会发生(不同的操作系统,不同版本的CLR)。 – 2011-01-05 22:23:58

+0

一个相关的帖子 - [C#构造函数执行顺序](https://stackoverflow.com/q/1882692/465053)。 – RBT 2018-02-14 11:48:43

回答

42

链接的构造函数将在定义构造函数的主体之前立即被调用。生成的IL序列是立即对其他构造函数的call,随后是从构造函数中的语句生成的IL。

所以,如果你链接到另一个构造函数,并且构造函数调用InitializeComponent()调用构造函数不应该调用此方法。

例如,给定此示例类:

class Foo { 
    public int A, B; 

    public Foo() : this(1) { 
     B = 2; 
    } 

    public Foo(int a) { 
     A = a; 
    } 
} 

这是产生IL:

.class private auto ansi beforefieldinit Foo 
     extends [mscorlib]System.Object 
    { 
    .field public int32 A 
    .field public int32 B 

    // method line 1 
    .method public hidebysig specialname rtspecialname 
      instance default void '.ctor'() cil managed 
    { 
     .maxstack 8 
     IL_0000: ldarg.0 
     IL_0001: ldc.i4.1 
     IL_0002: call instance void class Foo::'.ctor'(int32) 
     IL_0007: ldarg.0 
     IL_0008: ldc.i4.2 
     IL_0009: stfld int32 Foo::B 
     IL_000e: ret 
    } // end of method Foo::.ctor 

    // method line 2 
    .method public hidebysig specialname rtspecialname 
      instance default void '.ctor' (int32 a) cil managed 
    { 
     .maxstack 8 
     IL_0000: ldarg.0 
     IL_0001: call instance void object::'.ctor'() 
     IL_0006: ldarg.0 
     IL_0007: ldarg.1 
     IL_0008: stfld int32 Foo::A 
     IL_000d: ret 
    } // end of method Foo::.ctor 

    } // end of class Foo 

注意,无参数构造分配2到B场之前调用其他构造。

+0

完美。这就是我想的,谢谢 – JeffE 2011-01-05 22:22:12

+0

不会MSIL导致循环引用? (我知道它不会但我不明白为什么)似乎.ctor()正在调用.ctor(int32 a),反之亦然。任何人都可以澄清为什么这不会发生? – arviman 2014-07-15 06:39:47

+3

@arviman'Foo:.ctor()'调用'Foo:.ctor(int32)',但又调用'System.Object:.ctor()',*** not ***'Foo :.构造函数()'。 – cdhowie 2014-07-15 14:32:30

9

首先调用this(1)构造函数。

至于第二个问题,由于InitializeComponent和其他形式继承问题,我建议你使用组合而不是继承。

+0

我知道表单继承的一些问题,但它是我的项目的最佳解决方案 – JeffE 2011-01-05 22:24:05

5

在这样的问题上寻找答案的地方是C# Language Specification。在第10.11.1 ,构造函数初始化你可以阅读(重点是我的):

所有实例构造函数(除了 那些类对象)隐含 包括另一 实例构造之前调用立即 构造函数体。

此外读数表明:

  • 如果构造的形式为base(arguments)的实例构造函数的初始化,从直接基类的构造将被调用。
  • 如果构造函数具有形式为this(argument)的实例构造函数初始值设定项,则将调用该类中的构造函数。
  • 如果未提供实例构造函数初始值设定项,则将自动添加base()
+0

感谢您将c#语言规范引入我的注意 – Ronnie 2016-03-08 13:43:22