C#空传播运算符/条件访问表达式&if块

Phi*_*tle 19 c# null language-features c#-6.0

空传播运营商/条件接入表达在未来看起来像一个非常方便的功能.但我很好奇它是否有助于解决检查子成员是否为null然后在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!");
  }
Run Code Online (Sandbox Code Playgroud)

c?.Object?.Any()编译吗?如果传播运算符短路(我认为这是正确的术语)为null,那么你有if (null),这是无效的.

C#团队是否会解决这个问题,或者我是否错过了null传播运算符的预期用例?

Eld*_*iev 42

它不会这样工作.您可以跳过说明并查看下面的代码:)

如您所知,?.如果子成员为null,则运算符将返回null.但是,如果我们试图获得一个不可为空的成员,比如Any()返回的方法,会发生bool什么?答案是编译器将"包装"一个返回值Nullable<>.例如,Object?.Any()将给我们bool?(这是Nullable<bool>),而不是bool.

唯一不允许我们在if语句中使用这个表达式的是它不能被隐式地转换为bool.但你可以明确地进行比较,我更喜欢比较true这样:

if (c?.Object?.Any() == true)
    Console.Write("Container has items!");
Run Code Online (Sandbox Code Playgroud)

感谢@DaveSexton还有另一种方式:

if (c?.Object?.Any() ?? false)
    Console.Write("Container has items!");
Run Code Online (Sandbox Code Playgroud)

但至于我,比较true似乎更自然:)

  • 或者,有些人可能更喜欢使用空合并运算符:`if(c?.Objects?.Any()?? false){...}` (4认同)

Hab*_*bib 6

空条件运算符将返回null或表达式结尾处的值.对于值类型它将返回结果Nullable<T>,因此在您的情况下它将是Nullabe<bool>.如果我们查看C#中即将发布的功能 文档中的示例(此处指定),它有一个示例:

int? first = customers?[0].Orders.Count();
Run Code Online (Sandbox Code Playgroud)

在上面的例子中int,Nullable<int>将返回而不是.因为bool它会回来Nullable<bool>.

如果您在Visual Studio"14"CTP中尝试以下代码:

Nullable<bool> ifExist = c?.Objects?.Any();
Run Code Online (Sandbox Code Playgroud)

上述行的结果将是Nullable<bool>/ bool?.之后您可以进行比较,例如:

使用null-coalescing运算符?

 if (c?.Object?.Any() ?? false)
Run Code Online (Sandbox Code Playgroud)

使用Nullable<T>.GetValueOrDefault方法

if ((c?.Objects?.Any()).GetValueOrDefault())
Run Code Online (Sandbox Code Playgroud)

使用比较 true

if (c?.Objects?.Any() == true)
Run Code Online (Sandbox Code Playgroud)