В вашем случае нет никакой реальной разницы в функциональности. Однако есть проблема выяснить, где и как все инициализируется. Если я положил инициализацию в конструкторе, у меня есть два больших преимущества:
Все инициализировано в одном месте; Мне не нужно идти на охоту за тем, будет ли и где он будет установлен.
Если я хочу, я могу передать аргументы в конструктор Bar, основываясь на том, как я настраиваю содержимое. Если инициализатор вне конструктора, я намного более ограничен в том, как я могу инициализировать материал.
Честно говоря, IDE помогает немного с # 1 ... хотя это не дергать меня от кода я просто глядя на мои занятия редко бывают настолько велики, чтобы сделать повторное обнаружение вещи вопрос , Так что, если мне не нужно № 2, я так же могу сделать это в любом случае в зависимости от проекта и моего настроения. Тем не менее, для больших проектов я хочу, чтобы весь код init был в одном месте.
Edit:
ОК, по-видимому, есть разница между ними. Но случай, когда это имеет значение, встречается редко.
Я создал следующие классы:
class Program
{
public Program() { Console.WriteLine(this); }
static void Main(string[] args)
{
other p = new other();
Console.WriteLine(p);
Console.ReadLine();
}
}
class other : Program
{
string s1 = "Hello";
string s2;
public other() { s2 = "World"; }
public override string ToString() { return s1 + s2; }
}
Теперь, что я нашел, было немного удивительно, и неожиданно (если вы не читали C# спецификации).
Это то, что конструктор other
класса компилируется:.
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 29 (0x1d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldstr "Hello"
IL_0006: stfld string ConsoleApplication1.other::s1
IL_000b: ldarg.0
IL_000c: call instance void ConsoleApplication1.Program::.ctor()
IL_0011: ldarg.0
IL_0012: ldstr "World"
IL_0017: stfld string ConsoleApplication1.other::s2
IL_001c: ret
} // end of method other::.ctor
сведению призыв к Программе :: т е р (конструктор базового класса), зажатый между двумя ldstr
/stfld
пар (те, что установлено s1
и s2
). Значение, когда работает базовый конструктор, s2
еще не установлен.
Программа, для справки, выводит следующее:
Hello
HelloWorld
, потому что в конструктор Программы, Console.WriteLine(obj)
называется obj.ToString()
, который (так как объект уже other
) был other::ToString()
. Поскольку s2
еще не был установлен, мы не получили «Мир» в первый раз. Если бы мы делали что-то более склонное к ошибкам, чем просто печатать материал, это могло бы вызвать реальные проблемы.
Теперь это уродливый пример, призванный быть патологическим случаем. Но это отличный аргумент против вызова виртуальных функций в вашем конструкторе. Не делая этого, этот полом был бы невозможен. Это единственный раз, когда вам действительно нужно беспокоиться о различии: когда конструктор базового класса вызывает виртуальные методы, которые вы переопределили, которые полагаются на значения любых полей, которые устанавливаются в конструкторе. Довольно узкое окно прерывистости, но да.
Возможный дубликат: http://stackoverflow.com/questions/4219759/create-an-object-in-the-constructor-or-at-top-of-the-class или: http: // stackoverflow. com/questions/298183/c-member-variable-initialization-best-practice –
Спасибо, что поймали обманов, Yodan –