[英]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.