【问题标题】:Null-Conditional Operator空条件运算符
【发布时间】:2017-08-25 20:10:31
【问题描述】:

var a = b?.c.d;

这个表达式不应该总是给出编译错误吗?如果 b 为 null,则传播 null 值,因此 c 也将为 null,因此也需要此运算符。据我了解,在表达式中使用此运算符会像病毒一样传播。

但是 Visual Studio 2015 和 Resharper 都没有对我说什么,我在这里错过了什么吗?

【问题讨论】:

  • 为什么会是编译器错误?如果b 为空,则表达式的计算结果为空。如果不是,则表达式返回 b.c.d 的结果。
  • 不,如果 b 已经为空,则根本不会评估 c,从而使 a 只是 null
  • 我不明白这个问题;如果bnull,则表达式不会被进一步计算,而是产生null,因此c 不会发生任何事情。
  • 您希望生成什么编译器错误?
  • 你有没有想过var a = (b?.c).d;

标签: c# .net null-conditional-operator


【解决方案1】:

操作符只是语法糖:

MyType a = b == null ? 
    null: 
    b.c.d;

我不清楚为什么这会引发编译错误。

如果 b 为 null,则传播 null 值,因此 c 也将为 null,因此也需要此运算符

这不是真的。实际上,当b 为空时,c 甚至不存在,因为没有该成员可以存在的实例。所以简而言之,运算符只返回 null 并省略对 c 甚至 d 的进一步评估。

【讨论】:

  • 这不是有效的转换。 a总是被分配一个新值,尽管该值可能是null
  • var a = (b == null) ? null : b.c.d;
  • 另请注意,b 实际上并没有被多次评估,所以你的糖也不适合这个原因,尽管现在更接近了。
  • 如果b 定义为:class CurrentClass { static bool wasCalledBefore; static B { get { if(wasCalledBefore) { return null; } wasCalledBefore = true; return new B { c = new C { d = new D(), }, }; } } }
【解决方案2】:

如果bnull,则此运算符会短路并返回null

【讨论】:

    【解决方案3】:
    var a = b == null ? null : b.c.d
    

    这就是该语句在旧方式中的样子,?. 运算符在它之前为 null 时不会看起来更深,它只是返回 null,但是你会在 b 是已定义但b.c == null,因为您没有写为var a = b?.c?.d

    【讨论】:

      【解决方案4】:

      请注意:

      var a1 = b?.c.d;
      

      完全不同于:

      var a2 = (b?.c).d;
      

      简单地解释一元运算符?. 的工作原理并不容易(是的,一元!)。但想法是,如果?. 之前的表达式为空,则跳过“操作”“链”的其余部分。

      所以对于a1,只要b 恰好为空,您就会得到成员d(或该类型的Nullable<>,如果需要)携带的编译时类型的空值。当b 恰好为非空时,您将得到与b.c.d 相同的结果,如果b.c 为空,则可能会失败。

      但是a2 完全不同。如果b 为空,它总是会爆炸,因为括号(b?.c) 将是空引用,而下一个. 运算符将导致NullReferenceException。 (我在这里假设c 在编译时有一个引用类型。)

      所以不要认为有一种“左结合”可以让b?.c.d 等同于(b?.c).d


      您可以在this answer in another thread 中找到初步 C# 语言规范的链接;他们在第 7.7.1 节中提到 Null 条件运算符作为一元运算符。

      【讨论】:

        猜你喜欢
        • 2017-12-01
        • 1970-01-01
        • 2020-11-29
        • 1970-01-01
        • 1970-01-01
        • 2014-12-31
        • 2017-06-24
        • 1970-01-01
        相关资源
        最近更新 更多