С# - Нижняя граница для установки начального значения в декларации
Есть ли недостаток в классе, например:
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"]
.