Безопасно ли переписать следующий код:
bool b = foo.bar.HasValue ? foo.bar.Value : false;
к
bool b = foo.bar.Value ?? false;
где bar
- тип с нулевым значением bool?
Безопасно ли переписать следующий код:
bool b = foo.bar.HasValue ? foo.bar.Value : false;
к
bool b = foo.bar.Value ?? false;
где bar
- тип с нулевым значением bool?
Самое легкое исправление есть
bool b = foo.bar.GetValueOrDefault();
который также на самом деле дешевле, чем .Value
, поскольку он не учитывает проверку значения. Он по умолчанию будет default(T)
, что действительно false
здесь (он просто возвращает значение базового поля T
без каких-либо проверок вообще).
Если для default(T)
требуется другое значение по умолчанию:
var value = yourNullable.GetValueOrDefault(yourPreferredValue);
Что вы хотите:
bool b = foo.bar ?? false;
Это (удивительно) безопасное и предполагаемое использование для оператора с нулевым коалесцированием.
оператор называется оператором с нулевым коалесцированием и используется для определения значения по умолчанию для типов с нулевыми значениями, а также ссылочных типов. Он возвращает левый операнд, если он не равен нулю; в противном случае он возвращает правый операнд.
Источник: http://msdn.microsoft.com/en-us/library/ms173224.aspx
В случае Nullable<T>
он функционально эквивалентен Nullable<T>.GetValueOrDefault(T defaultValue)
.
Код:
bool b = foo.bar.Value ?? false;
Вызывает ошибку компилятора, потому что вы не можете применить оператор к значениям типов, а Nullable<T>.Value
всегда возвращает тип значения (или генерирует исключение, когда нет значения).
Нет - это не безопасно.
Строка:
bool b = foo.bar.Value ?? false;
будет вызывать InvalidOperationException, если foo.bar не имеет значения.
Вместо этого используйте
var b = foo.bar ?? false;
Обновление. Я только что узнал о .GetValueOrDefault();
из других ответов - это похоже на очень хорошее предложение для использования!
Обновление 2 - @ProgrammingHero ответ также правильный (+1 добавлен!) - строка:
bool b = foo.bar.Value ?? false
на самом деле не будет компилироваться - из-за Error 50 Operator '??' cannot be applied to operands of type 'bool' and 'bool'
Неа.
Свойство Value возвращает значение if один присваивается, в противном случае Исправление System.InvalidOperationException выброшены.
От: http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.80%29.aspx
Итак, если hasValue является ложным, тогда вы получите исключение, возникшее во втором, когда вы попытаетесь его запустить.
ffoo.bar ?? false
было бы более безопасным использование
bar.Value ?? false
имеет ошибку компиляции, потому что левый операнд оператор должен иметь ссылочный или нулевой тип.
Может быть, вы посмотрите на эту статью в Stackoverflow тоже - это элегантная проверка нуля в стиле obj.IfNotNull(lambdaExpression)
- возврат объекта, который вы хотите, если obj is не null, иначе просто null (но не выбрасывая исключение).
Я использовал его с Entity Framework, если вы обращаетесь к ссылочному объекту, например.
var str=Entity1.Entity2.IfNotNull(x=>x.EntityDescription) ?? string.Empty
который возвращает EntityDescription
, содержащийся в Entity2
, на который ссылается Entity1
- или пустая строка, если любой объект Entity1
или Entity2
равен null
. Без IfNotNull
вы получите длинное и уродливое выражение.
Метод расширения IfNotNull
определяется там следующим образом:
public static TOut IfNotNull<TIn, TOut>(this TIn v, Func<TIn, TOut> f)
where TIn : class
where TOut: class
{
if (v == null) return null; else return f(v);
}
Update:
Если вы обновите код до С# версии 6.0 (.NET Framework 4.6 - но похоже, поддерживает устаревшие фреймворки 4.x тоже), есть доступный новый оператор, облегчающий эту задачу: Оператор "elvis" ?.
.
Он работает следующим образом:
var str=(Entity1.Entity2?.EntityDescription) ?? string.Empty
В этом случае, если Entity2
равно null
, оценка останавливается и (...)
становится null
- после чего часть ?? string.empty
заменяет null
на string.Empty
. Другими словами, он работает так же, как .IfNotNull(...)
.
foo.bar.Value представляет значение, отличное от нуля, когда оно есть, и выдает исключение InvalidOperationException, если нет реального значения.