2010-06-23 69 views
8

C#中的??運算符在評估時是否使用短路?``````操作符是否使用短路?

var result = myObject ?? ExpressionWithSideEffects(); 

myObject非空的ExpressionWithSideEffects()結果沒有被使用,但會ExpressionWithSideEffects()可以完全跳過?

回答

7

是的。與以往一樣,C#語言規範是權威源。

從C#3.0規範,部分7.12(V3,而不是4,作爲V4規範進入動態細節是不是真的與此有關):

類型表達a ?? b取決於其隱式轉換在操作數的類型之間可用。按照偏好的順序, b是A0,A或B,其中A是a的類型,B是b的類型(假設b具有類型),並且A0是A的基礎類型(如果A是可空類型),否則A 。

  • 如果A不是空類型或引用類型,一個編譯時錯誤發生 :具體地,如 如下a ?? b被處理。
  • 如果A是可以爲空的類型,並且存在從b到 A0的隱式轉換,則結果類型爲A0。在 運行時,首先評估a。如果 不爲空,則將a解包爲輸入 A0,這將成爲結果。 否則,評估b並將 轉換爲A0類型,並將其變成 的結果。
  • 否則,如果存在從b到A的隱式轉換,則結果類型爲 A.在運行時,首先計算a。 如果a不爲空,則a成爲 結果。否則,b被評估並且 轉換爲A型,並且這變成 結果。
  • 否則,如果b具有類型B並且存在從A0到 B的隱式轉換,則結果類型爲B.在運行時,首先計算出 a。如果a不是 爲空,則將a打開以輸入A0 (除非A和A0是相同類型) 並轉換爲類型B,並且此 成爲結果。否則,b被 評估併成爲結果。
  • 否則,a和b不兼容,併發生編譯時錯誤。

第二個,第三個和第四個項目符號是相關的。


有到過一下你碰巧使用編譯器是否是真理的實際源的哲學討論......是關於語言那是什麼意味着做的真相或者它目前確實是

+0

對腳註...我認爲這就是爲什麼我們都喜歡埃裏克Lippert正在:) – 2010-06-23 16:49:09

+1

@Matthew:很多原因之一,是的。 Eric的一個有趣的方面是他可以作爲spec *和*編譯器的人類化身...... – 2010-06-23 17:10:08

10

是的,它確實短路。

下面是LinqPad測試一個片段:

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

第一個聚結不工作,而第二個不擲(格式字符串是無效的)拋出異常。

+0

廢話,我能感覺到自己被拉進事件視界! – Will 2010-06-23 17:39:58

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"); 
    } 

這些不是最好的測試名稱,但你明白了。它表明,空合併操作符按預期短路。

+0

我意識到ArgumentException是一個奇怪的選擇,它只是第一個想到的異常類型。 – CaffGeek 2010-06-23 16:43:37

+3

這不是我們進行單元測試的原因。這就是爲什麼我們有語言規範。特別是,如果我們有單元測試,但沒有語言規範,我們只會知道在被測試的情況下會發生什麼。但是,如果我們有語言規範但沒有單元測試,我們仍然會知道在一般情況下該語言的意圖。誠然,單元測試有助於驗證編譯器是否實際實現了語言規範......但我總是寧願達到規範而不是像這樣的問題進行單元測試。 – 2010-06-23 16:44:37

+0

@Jon Skeet,touche。我仍然喜歡寫快速測試來驗證我不確定的事情。我不一定會保留它。編譯器總是可能實現了不合適的規範... – CaffGeek 2010-06-23 16:49:26