``??``运算符是否使用短路?

时间:2010-06-23 16:28:31

标签: c# logic operator-keyword

C#中的??运算符在评估时是否使用短路?

var result = myObject ?? ExpressionWithSideEffects();

myObject非空时,ExpressionWithSideEffects()的结果未被使用,但ExpressionWithSideEffects()会被完全跳过吗?

3 个答案:

答案 0 :(得分:10)

是的,它会短路。

这是在LinqPad中测试的片段:

string bar = "lol";
string foo = bar ?? string.Format("{2}", 1);
foo.Dump();
bar = null;
foo = bar ?? string.Format("{2}", 1);
foo.Dump();

第一个coalesce在没有抛出异常的情况下工作,而第二个抛出则抛出(格式字符串无效)。

答案 1 :(得分:7)

是的。与以往一样,C#语言规范是权威来源 1

从C#3规范,第7.12节(v3而不是4,因为v4规范进入动态细节,这里没有真正相关):

  

表达式a ?? b的类型取决于操作数类型之间可用的隐式转换。按优先顺序排列,类型为?? b是A0,A或B,其中A是a的类型,B是b的类型(假设b具有类型),如果A是可空类型,则A0是A的基础类型,否则A 。具体而言,a ?? b被处理为   如下:

     
      
  • 如果A不是可空类型或引用类型,则为编译时错误   发生。
  •   
  • 如果A是可空类型,则从b到存在隐式转换   A0,结果类型为A0。在   运行时,首先评估a。如果一个   不是null,a是打开的类型   A0,这就是结果。   否则,b被评估并且   转换为A0型,这就变成了   结果。
  •   
  • 否则,如果从b到A存在隐式转换,则结果类型为   A.在运行时,首先评估a。   如果a不为null,则a成为   结果。否则,b被评估并且   转换为A型,这就变成了   结果。
  •   
  • 否则,如果b具有类型B并且存在从A0到A0的隐式转换   B,结果类型为B.在运行时,   首先评估a。如果不是   null,a被解包为A0类型   (除非A和A0是相同的类型)   并转换为B型,这个   成为结果。否则,b是   评估并成为结果。
  •   
  • 否则,a和b不兼容,并发生编译时错误。
  •   

第二,第三和第四发子弹是相关的。


1 关于你碰巧使用的编译器是否是实际的真实来源 - 还有一个哲学讨论......关于语言的真相是什么是意味着要做什么或者当前做什么

答案 2 :(得分:0)

这就是我们进行单元测试的原因。

    [TestMethod]
    public void ShortCircuitNullCoalesceTest()
    {
        const string foo = "foo";
        var result = foo ?? Bar();
        Assert.AreEqual(result, foo);
    }

    [TestMethod]
    [ExpectedException(typeof(ArgumentException))]
    public void ShortCircuitNullCoalesceFails()
    {
        const string foo = null;
        var result = foo ?? Bar();
    }

    private static string Bar()
    {
        throw new ArgumentException("Bar was called");
    }

这些不是最好的测试名称,但你明白了。它显示空合并运算符如预期的那样短路。