Переписать 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, если нет реального значения.