Подтвердить что ты не робот

Заказ цепочки конструкторов

Если вы вызываете вызовы конструктора с помощью синтаксиса:

public frmConfirm(): this(1)

когда вызван перегруженный конструктор? Кроме того, может кто-нибудь подтвердить, что если класс является формой, проблемы возникнут из-за вызова InitializeComponent() в обоих конструкторах?

4b9b3361

Ответ 1

Прикованный конструктор будет вызываться непосредственно перед телом определяющего конструктора. Созданная последовательность 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

Обратите внимание, что конструктор no-arg вызывает другой конструктор перед назначением 2 в поле B.

Ответ 2

Сначала вызывается конструктор this(1).

Что касается второго вопроса, из-за InitializeComponent и других проблем с наследованием формы, я бы предложил использовать композицию вместо наследования.

Ответ 3

Место поиска ответов на такой вопрос - С# Language Specification. В разделе 10.11.1 инициализаторы конструктора вы можете прочитать (акцент мой):

Все конструкторы экземпляров (кроме те для объекта класса) неявно включить вызов другого конструктор экземпляров немедленно перед конструктором-телом.

Дальнейшее чтение показывает, что:

  • Если конструктор имеет инициализатор конструктора экземпляра формы base(arguments), будет вызван конструктор из прямого базового класса.
  • Если конструктор имеет инициализатор конструктора экземпляра формы this(argument), будет вызван конструктор в самом классе.
  • Если не предусмотрен инициализатор конструктора экземпляра, base() будет добавлен автоматически.