—— 為什么2/6*4不等于1/12?
🔍 一、表達式求值順序為何重要?
表達式如精密儀器,子表達式求值順序直接決定結果。例如:
int result = 3 * 5 + 2;
- 若先算乘法:(3*5)+2 = 17 ?
- 若先算加法:3*(5+2)=21 ?
(實際結果為17,乘法優先級更高) - ?? 關鍵結論:編譯器不是從左到右機械執行,而是通過優先級與結合性規則構建計算樹。
🎚? 二、優先級:C#的14層運算符金字塔
C#有45+運算符和14級優先級(遠超小學的四則運算兩級)。核心規則:
優先級組 | 典型運算符 | 示例 |
---|---|---|
最高級 | ()、[]、. | (a+b)*c |
單目運算 | ++、–、! | !isValid |
乘除類 | *、/、% | 2/6*4 → (2/6)*4 |
加減類 | +、- | x+5-3 |
比較類 | >、==、!= | age >= 18 |
邏輯類 | &&、 | |
最低級 | =、+= | sum += value |
💡 黃金法則:乘除優先加減,比較先于邏輯,賦值永遠最后。
?? 三、結合性:當優先級相同時誰說了算?
左結合(絕大多數運算符):從左向右計算
double v = 2 / 6 * 4; // 等價于 (2/6)*4 ≈ 0.333*4=1.333
右結合(賦值/條件運算符):從右向左計算
int a, b, c;
a = b = c = 10; // 等價于 a=(b=(c=10))
?? 易錯點:x = y += 3 → 先執行y+=3,再賦值給x
🛡? 四、括號:超越規則的終極武器
括號強制覆蓋所有優先級與結合性規則:
int magic = 3 * (5 + 2); // 結果為21而非17
嵌套規則:
- 最內層括號優先計算
- 逐層向外展開
int v = ((2 + 3) * (4 - 1)) / 2; // 5*3/2=7
💎 五、開發者必知實戰建議
防御性編程:
對復雜表達式顯式添加括號,即使優先級明確
// 模糊寫法
if (a & b == c)
// 清晰寫法(&優先級低于==)
if ((a & b) == c)
避免副作用陷阱:
int i = 0;
int k = i++ + i; // 未定義行為!不同編譯器結果可能不同
性能優化:
將高開銷計算放在短路運算符右側
if (isValid && ExpensiveOperation()) // 若isValid=false則跳過耗時操作
🌟 終極結論
括號 > 優先級 > 結合性
當表達式復雜度上升時,顯式括號是代碼可讀性與正確性的最佳保障!
📚 擴展思考:
x = y ?? z * 100 如何計算?
(提示:??優先級低于但高于=,實際等價于x = (y ?? (z100)))
本文適用于C# 10規范,部分規則在舊版本或有差異。技術配圖可參考原文圖表。