Не обязательно плохо инициализировать значения вне конструктора, и проблема, которую вы имеете здесь:
string _string;
public ConstructorExample2()
{
_string = "John";
}
В том, что если у вас есть несколько конструкторов, вы должны помнить, чтобы либо
1. Переинициализировать _string в каждом конструкторе
2. Выделить логику в общий метод и вызывать этот метод в каждом конструкторе
3. Вызывать конструктор с логикой в нем из других конструкторов. (Цепочка конструкторов)
.
Теперь это не обязательно проблема, но вы должны помнить об этом. Инициализация вне конструктора делает это за вас. Вам нужно не забыть сделать еще одну вещь.
Microsoft FxCop по умолчанию рекомендует инициализаторы полей вместо использования конструктора. Этот вопрос также дублирует этот и должен дать некоторое представление.
При использовании статических классов вам придется обратить внимание на некоторые тонкости, которые рассматриваются в этом вопросе.
Не уверен насчет C#, но в исходном коде Java, похоже, предпочитают конструктор, пример:
public class String{
char[] value;
int offset;
...
public String(){
value = new char[0];
offset = 0;
...
}
}
Думаю, для простых инициализаций вроде этой вполне можно делать это в объявлении. Однако я не понимаю аргумента об обработке ошибок. Даже если при инициализации возникнет исключение, я думаю, вы обнаружите, что ваш обычный механизм обработки ошибок будет работать так же. Он все равно выбросит исключение, когда вы вызовете конструктор.
Если инициализация переменной будет такой же, независимо от того, какие аргументы передаются конструктору, тогда нет смысла загромождать метод конструктора ненужным кодом инициализации. В этом случае я инициализирую на месте.
Лучше инициализировать поля в конструкторе. Таким образом, если / когда добавлен другой конструктор, вы знаете, что все поля начинаются со значений NULL / значений по умолчанию, и вы можете инициализировать их соответствующим образом.
Обратите внимание, что вся такая инициализация на уровне объявления поля будет выполняться один раз для каждой цепочки конструкторов, даже если конструктор сам по себе устанавливает для поля что-то другое.
Если вы объедините конструкторы в цепочку, поля будут инициализированы в первом вызываемом общем конструкторе.
Посмотрите на этот пример:
using System;
namespace ClassLibrary3
{
public class Class1
{
private string _Name = "Lasse";
public Class1()
{
}
public Class1(int i)
: this()
{
}
public Class1(bool b)
{
_Name = "Test";
}
}
}
Этот код компилируется следующим образом:
using System;
namespace ClassLibrary3
{
public class Class1
{
private string _Name;
public Class1()
{
_Name = "Lasse"
}
public Class1(int i)
: this()
{
// not here, as this() takes care of it
}
public Class1(bool b)
{
_Name = "Lasse"
_Name = "Test";
}
}
}
Я склонен инициализировать вещи в аксессоре get, где они используются впервые. Если null, то инициализировать и все такое.
В приведенном выше примере присвоение "John" к _string не имеет логической зависимости от каких-либо переменных и поэтому должно находиться вне конструктора в инициализаторе поля.
До тех пор, пока невозможно инициализировать объект в неиспользуемом состоянии, это не имеет значения.
Когда код будет скомпилирован, оба подхода все равно будут одинаковыми.
Я предпочитаю инициализировать такие простые поля вне конструктора.
Это не должно вызывать никаких проблем, поскольку компиляция в любом случае перемещает эти инициализации в конструктор во время компиляции.