48

If you chain constructor calls using the syntax:

public frmConfirm(): this(1)

when is the overloaded constructor called? Also, can somebody confirm that if the class is a form, problems will arise from having the InitializeComponent() call in both constructors?

JeffE
  • 794
  • 2
  • 9
  • 15
  • 5
    @madmik3: it sure is simple to write code to see what happens. The question is then whether that is *guaranteed* to happen in all circumstances (different OS, different versions of the CLR). – Fredrik Mörk Jan 05 '11 at 22:23
  • 1
    A related post - [C# constructor execution order](https://stackoverflow.com/q/1882692/465053). – RBT Feb 14 '18 at 11:48

3 Answers3

49

The chained constructor will be called immediately prior to the body of the defining constructor. The IL sequence generated is an immediate call to the other constructor, followed by the IL generated from the statements in the constructor.

So if you chain to another constructor and that constructor calls InitializeComponent() the calling constructor should not call this method.

For example, given this sample class:

class Foo {
    public int A, B;

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

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

This is the generated 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

Note that the no-arg constructor calls the other constructor before assigning 2 to the B field.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • won't the MSIL cause a circular reference? (i know it won't but i can't understand why) Seems like .ctor() is calling .ctor(int32 a) and vice versa. Can anyone clarify why this is not happening? – arviman Jul 15 '14 at 06:39
  • 4
    @arviman `Foo:.ctor()` is calling `Foo:.ctor(int32)`, but that in turn calls `System.Object:.ctor()`, ***not*** `Foo:.ctor()`. – cdhowie Jul 15 '14 at 14:32
14

The this(1) constructor is called first.

As far as your second question goes, because of the InitializeComponent and other issues with form inheritance, I'd suggest you use composition instead of inheritance.

Jacob
  • 77,566
  • 24
  • 149
  • 228
10

The place to look for answers on a question like this is the C# Language Specification. In the section Constructor initializers you can read (emphasis is mine):

All instance constructors (except those for class object) implicitly include an invocation of another instance constructor immediately before the constructor-body.

Further reading shows that:

  • if the constructor has an instance constructor initializer of the form base(arguments), a constructor from the direct base class will be invoked.
  • if the constructor has an instance constructor initializer of the form this(argument), a constructor in the class itself will be invoked.
  • if no instance constructor initializer is provided, base() will be added automatically.
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343