簡體   English   中英

C#中的三元運算符關聯性 - 我可以依賴它嗎?

[英]Ternary operator associativity in C# - can I rely on it?

啊,你不喜歡一個好的三元濫用嗎? :)考慮以下表達式:

true ? true : true ? false : false

對於那些現在完全感到困惑的人,我可以告訴你,這個評估是真的 換句話說,它等同於:

true ? true : (true ? false : false)

但這可靠嗎? 我能否確定在某些情況下不會出現這種情況:

(true ? true : true) ? false : false

有些人可能會說 - 好吧,只需添加括號或完全不使用它 - 畢竟,眾所周知,三元運算符是邪惡的!

當然它們是,但在某些情況下它們確實有意義。 對於好奇的 - 我正在擰干通過一系列屬性比較兩個對象的代碼。 如果我像這樣冷寫它會很好:

obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4)

簡潔明了。 但它確實取決於三元運算符的相關性,就像第一種情況一樣。 括號只會使意大利面條脫離它。

那么 - 這是指定的嗎? 我找不到它。

是的,您可以依賴於此(不僅在C#中,而且在所有(我知道)其他語言( 除了PHP ...去圖)與條件運算符)並且您的用例實際上是一種非常常見的做法,盡管有些人厭惡它。

ECMA-334(C#標准)中的相關部分是14.13§3:

條件運算符是右關聯的,這意味着操作從右到左分組。 [示例:表單形式a ? b : c ? d : e a ? b : c ? d : e a ? b : c ? d : e被評估為a ? b : (c ? d : e) a ? b : (c ? d : e) 最后的例子]

如果你不得不問,不要。 任何人閱讀你的代碼將不得不經過你做了同樣的過程,一遍又一遍,需要在來看待該代碼的任何時間。 調試這樣的代碼並不好玩。 最終它只會被改為使用括號。

回復: “嘗試用括號寫下整個​​事情。”

result = (obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
         (obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
         (obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
                                     obj1.Prop4.CompareTo(obj2.Prop4))))

澄清:

  • “如果不得不問,不要。”
  • “任何人都在閱讀你的代碼...”

遵循項目中常見的約定是如何保持一致性,從而提高可讀性。 認為你可以編寫每個人都可讀的代碼 - 包括那些甚至不懂語言的人 - 這是一個愚蠢的錯誤!

但是,保持項目的一致性是一個有用的目標,並且不遵循項目的公認慣例會導致辯論減少解決實際問題。 那些閱讀代碼的人應該知道項目中使用的常見和接受的約定,甚至可能是直接在其上工作的其他人。 如果他們不了解他們,那么他們應該學習它們,並且應該知道在哪里尋求幫助。

也就是說 - 如果使用沒有括號的三元表達式是項目中常見且被接受的約定,那么一定要使用它! 您必須要求表明它在您的項目中不常見或被接受。 如果你想改變你的項目中的約定,那么明確地明確無誤,將其標記為與其他項目成員討論的內容,然后繼續。 這意味着使用括號或使用if-else。

最后一點要思考,如果你的一些代碼看起來很聰明:

調試的難度是首先編寫代碼的兩倍。 因此,如果您盡可能巧妙地編寫代碼,那么根據定義,您不夠聰明,無法對其進行調試。 - Brian W. Kernighan

括號中有損於代碼可讀性的斷言是錯誤的假設。 我發現括號表達式更清晰。 就個人而言,我會使用括號和/或重新格式化幾行來提高可讀性。 重新格式化多行並使用縮進甚至可以消除對括號的需要。 而且,是的,你可以依賴於這樣一個事實,即關聯的順序是確定性的,從右到左。 這允許表達式以預期的方式從左到右進行評估。

obj1.Prop1 != obj2.Prop1
     ? obj1.Prop1.CompareTo(obj2.Prop1)
     : obj1.Prop2 != obj2.Prop2
           ? obj1.Prop2.CompareTo(obj2.Prop2)
           : obj1.Prop3 != obj2.Prop3
                  ? obj1.Prop3.CompareTo(obj2.Prop3)
                  : obj1.Prop4.CompareTo(obj2.Prop4);

請參閱msdn: http//msdn.microsoft.com/en-us/library/ty67wk28%28VS.80%29.aspx

“如果condition為true,則計算第一個表達式並成為結果;如果為false,則計算第二個表達式並成為結果。只評估兩個表達式中的一個。”

x = cond1 ? result1
  : cond2 ? result2
  : cond3 ? result3
  : defaultResult;

VS

if (cond1) x = result1;
else if (cond2) x = result2;
else if (cond3) x = result3;
else x = defaultResult;

我喜歡第一個。

是的,您可以依賴條件運算符關聯性。 它在手冊中,在dcp友情提供的鏈接上,用一個例子表示為“條件運算符是右關聯的”。 並且,正如您所建議的那樣,我和其他人一致同意,您可以依賴它的事實允許更清晰的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM