С# - Нижняя граница для установки начального значения в декларации

Есть ли недостаток в классе, например:

class Example1
{
  protected string UserId = (string)Session["user"];
}
//versus

class Example2
{
  protected string UserId;
  public Example2()
  {
      UserId = (string)Session["user"];
  }
}

Если я всегда хочу установить это значение, есть ли недостаток в примере1?

UPDATE:
Сессия [ "user" ] устанавливается в Global.asax Session_Start. Так что если это не удастся. Ничто не должно работать в любом случае.

Ответ 1

Самая большая проблема заключается в том, что этот protected string UserId = (string)Session["user"]; терпит неудачу. У вас нет возможности грациозно разлагаться. Поместив его в конструктор и т.д. Вы можете проверить сеанс и принять решение о том, что делать.

Как правило, я только пытаюсь добавить значения, которые, как я знаю, будут успешными, например, UserId = -1; и т.д., а затем модифицируют их в блоке кода, когда мне это нужно. Вы никогда не знаете, когда что-то пойдет не так, и вам нужно оправиться от него.

Ответ 2

Основной недостаток заключается в том, что вы можете установить значение только с помощью одного оператора. Если, например, вы хотели проверить ключ сеанса, и если это не так, вы хотели бы присвоить ему значение, то вы не смогли бы это сделать, установив начальное значение.

Ответ 3

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

Ответ 4

Я настоятельно рекомендую использовать "безопасный" бросок.

UserId = Session["user"] as string;

Таким образом, если элемент сеанса не существует или не является строкой, вы не терпите неудачу. Вы просто получаете нуль, который вы можете проверить для использования UserId.

Ответ 5

AFAIK, нет реальной разницы между инициализаторами инициализации и инициализацией конструктора, за исключением порядка выполнения операторов, и тем фактом, что вы очень ограничены однострочными операторами в встроенном коде.

Порядок выполнения заключается в том, что инициализаторы значений выполняются перед любой конструкторской логикой в ​​неспецифическом порядке, поэтому, если какое-либо из инициализационных утверждений имеет побочные эффекты, вы можете столкнуться с некоторыми неприятными сюрпризами. Тем не менее, гарантируется, что этот код будет работать, поэтому нет возможности добавить дополнительный конструктор позже и забыть инициализировать некоторое поле.

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

Ответ 6

Рекомендация, которую я использую: Использовать инициализаторы полей для основных/значений, известных во время компиляции. Если вы делаете что-то вроде поиска глобальной коллекции или некоторой нетривиальной логики, переместите ее в ctor (для обработки ошибок/восстановления, как указывали другие).

Предполагая, что вы уверены, что ошибок не будет,

  • upside: инициализаторы полей легко читаются.
  • Недостаток: если у вас есть куча инициализаторов полей и нескольких костров, IL для инициализаторов будет вставлен в начало каждого ctor, ведущего к некоторому раздуванию IL. Таким образом, в этом случае вызов метода Initialize like будет лучше.

Кроме этого, я не вижу недостатков в инициализаторах поля.

Ответ 7

Трудно понять, как начать говорить, что это не очень хорошая идея по многим причинам. Первая сессия должна быть глобальной переменной, иначе ваш код даже не будет компилироваться. Я предполагаю, что сеанс в вашем контексте - это System.Web.HttpContext.Current.Session, поэтому ваш код даже не будет компилироваться. Предположим, что у вас есть сессия как глобальная переменная, тогда вы должны ее правильно инициализировать и назначить Session [ "user" ], так как вы собираетесь это делать? Затем вы создаете эту зависимость между вашим классом и сеансом, так как вы unit test? Плюс все другие причины из всех других ответов.

Ответ 8

Возможно, вам понадобится второй конструктор с другим значением UserId.

Ответ 9

AFAIK конструктор всегда вызывается после инициализации всех полей. Итак, в примере 2 вы сначала инициализируете поле до Null, а затем до (string)Session["user"].