Переписать HasValue на??? операторы
Безопасно ли переписать следующий код:
bool b = foo.bar.HasValue ? foo.bar.Value : false;
к
bool b = foo.bar.Value ?? false;
где bar
- тип с нулевым значением bool?
Ответы
Ответ 1
Самое легкое исправление есть
bool b = foo.bar.GetValueOrDefault();
который также на самом деле дешевле, чем .Value
, поскольку он не учитывает проверку значения. Он по умолчанию будет default(T)
, что действительно false
здесь (он просто возвращает значение базового поля T
без каких-либо проверок вообще).
Если для default(T)
требуется другое значение по умолчанию:
var value = yourNullable.GetValueOrDefault(yourPreferredValue);
Ответ 2
Что вы хотите:
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
всегда возвращает тип значения (или генерирует исключение, когда нет значения).
Ответ 3
Нет - это не безопасно.
Строка:
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'
Ответ 4
Неа.
Свойство Value возвращает значение if один присваивается, в противном случае Исправление System.InvalidOperationException выброшены.
От: http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.80%29.aspx
Итак, если hasValue является ложным, тогда вы получите исключение, возникшее во втором, когда вы попытаетесь его запустить.
Ответ 5
ffoo.bar ?? false
было бы более безопасным использование
Ответ 6
bar.Value ?? false
имеет ошибку компиляции, потому что левый операнд оператор должен иметь ссылочный или нулевой тип.
Ответ 7
Может быть, вы посмотрите на эту статью в 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(...)
.
Ответ 8
foo.bar.Value представляет значение, отличное от нуля, когда оно есть, и выдает исключение InvalidOperationException, если нет реального значения.