С# Null оператор распространения/выражение условного доступа и блоки if
Нулевой оператор распространения/выражение условного доступа, входящее в С# -6.0 выглядит довольно удобной функцией. Но мне любопытно, поможет ли это решить проблему проверки того, является ли дочерний элемент не нулевым, а затем вызывает логический метод для указанного дочернего элемента внутри блока if:
public class Container<int>{
IEnumerable<int> Objects {get;set;}
}
public Container BuildContainer()
{
var c = new Container();
if (/* Some Random Condition */)
c.Objects = new List<int>{1,2,4};
}
public void Test()
{
var c = BuildContainer();
//Old way
if ( null != c && null != c.Objects && c.Objects.Any())
Console.Write("Container has items!");
//C# 6 way?
if (c?.Object?.Any())
Console.Write("Container has items!");
}
Будет ли c?.Object?.Any()
скомпилировать? Если короткозамкнутый оператор распространения (предположим, что правый член) равен нулю, вы имеете if (null)
, что недопустимо.
Будет ли команда С# решать эту проблему или мне не хватает предполагаемого варианта использования для пустого оператора распространения?
Ответы
Ответ 1
Это не сработает. Вы можете просто пропустить объяснение и посмотреть код ниже:)
Как вы знаете, оператор ?.
возвращает значение null, если дочерний элемент равен NULL. Но что произойдет, если мы попытаемся получить член, не содержащий NULL, как метод Any()
, который возвращает bool
? Ответ заключается в том, что компилятор "обернет" возвращаемое значение в Nullable<>
. Например, Object?.Any()
даст нам bool?
(который Nullable<bool>
), а не bool
.
Единственное, что не позволяет нам использовать это выражение в выражении if
, состоит в том, что он не может быть неявным образом исполнен в bool
. Но вы можете сделать сравнение явно, я предпочитаю сравнивать с true
следующим образом:
if (c?.Object?.Any() == true)
Console.Write("Container has items!");
Благодаря @DaveSexton есть другой способ:
if (c?.Object?.Any() ?? false)
Console.Write("Container has items!");
Но для меня сравнение с true
кажется более естественным:)
Ответ 2
Оператор Null-условный возвращает null
или значение в конце выражения. Для типов значений Он вернет результат в Nullable<T>
, поэтому в вашем случае это будет Nullabe<bool>
. Если мы посмотрим на пример в документе для Предстоящие функции на С# (указанный здесь), у него есть пример:
int? first = customers?[0].Orders.Count();
В приведенном выше примере вместо int
, Nullable<int>
будет возвращено. Для bool
он вернет Nullable<bool>
.
Если вы попробуете следующий код в Visual Studio "14" CTP:
Nullable<bool> ifExist = c?.Objects?.Any();
Результат указанной выше строки будет Nullable<bool>
/bool?
. Позже вы можете сделать сравнение, например:
Используя оператор с нулевой связью
if (c?.Object?.Any() ?? false)
Использование Nullable<T>.GetValueOrDefault
Метод
if ((c?.Objects?.Any()).GetValueOrDefault())
Использование сравнения с true
if (c?.Objects?.Any() == true)