Подтвердить что ты не робот

С# Null оператор распространения/выражение условного доступа и блоки if

Нулевой оператор распространения/выражение условного доступа, входящее в выглядит довольно удобной функцией. Но мне любопытно, поможет ли это решить проблему проверки того, является ли дочерний элемент не нулевым, а затем вызывает логический метод для указанного дочернего элемента внутри блока 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), что недопустимо.

Будет ли команда С# решать эту проблему или мне не хватает предполагаемого варианта использования для пустого оператора распространения?

4b9b3361

Ответ 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)