2013-05-20 3 views
3

В чем разница между этими двумя?Нужен ли конструктор по умолчанию?

class Class1 
{ 
    public int a = 1; 
} 

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

Если ни один, я могу пропустить конструктор по умолчанию и инициализировать свои переменные, как в Class1?

+13

Это сделает разницу в _order_, что вещи случаются. –

+0

Мне нравится помещать инициализацию в конструктор, потому что, если вы делаете что-то более сложное и не получается, вы получите более конкретную ошибку, чем «не удалось инициализировать». – zimdanen

+0

В чем разница в заказе? – Robbert

ответ

1

В вашем конкретном примере инициализаторы полей (Class1) являются точными. Можно утверждать, что то, что не прекрасно это открытое поле, р я бы посоветовал либо:

// 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(); 
    } 
} 
7

Вызов new Class1() первых устанавливает a на 1, а затем вызывает конструктор базового класса.

Вызов new Class2() сначала вызывает конструктор базового класса, затем устанавливает a в 1.

Поскольку вы производны от object, конструктор базового класса ничего не делает. В других случаях это может иметь значение.

1

Вы не можете использовать инициализацию для каждого поля или для автоматических свойств. Конструктор дает вам возможность устанавливать значения для этих полей и свойств.

Следует отметить, что инициализация поля предваряется каждый конструктор в классе, кстати, поэтому писать конструктор по умолчанию (и имеющий все остальные конструкторы класса продолжают от него) может быть более эффективно в перспективу размера кода. Это способ, по которому конструктор по умолчанию может действительно пригодиться.

8

Вы не заметите разницу в вашем коде, но разница в том порядке, в котором вещи называются и инициализированы:

  1. Походного поле класса Инициализаторы выполняются.
  2. Инициализаторы полей базового класса запускаются.
  3. Выполняется конструктор базового класса.
  4. Производится построенный конструктор классов.

Таким образом, в вашем Class1 поле инициализируется в шаге 1. В вашем Class2 поле initialzed его значение 0 по умолчанию на шаге 1, а затем устанавливается в 1 на шаге 4.

Подробнее информация в серии статей Эрика Липперта Why do initializers run in the opposite order as constructors, part 1, part 2.

3

Разница заключается в том порядке, между вызовом конструктора и «а» настройкой поля, как вы можете увидеть в 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 
+1

для информации, вероятно, стоит использовать режим «освобождения»/«оптимизированный» при выводе IL-вывода - отладочные сборки иногда имеют заметные отличия («nop» - это большая подсказка, что это отладочная сборка) –

+0

хорошо наблюдаемый, отредактирован для отображения оптимизированного кода. – giacomelli

Смежные вопросы