C# 運算子依操作元個數分為一元、二元、三元三大類,另包含關鍵字形式的特殊運算子。理解分類體系與語法特徵,能快速識別運算式結構、掌握優先級邊界並正確使用現代語法糖。
依運算元個數分類
| 分類 | 運算元數 | 語法位置 | 代表運算子 | 子分類 |
| 一元運算子 | 1 | 前綴/後綴 | +x -x !x ~x ++x --x x++ x-- (T)x typeof(T) sizeof(T) await x nameof(x) default(T) ref x out x | 算術、邏輯、位元、遞增遞減、轉型、型別查詢、非同步、編譯期常數 |
| 二元運算子 | 2 | 中置 | a + b a - b a * b a / b a % b a && b a || b a & b a | b a ^ b a == b a != b a < b a > b a <= b a >= b a << b a >> b a ?? b a + b (字串/委派) a - b (委派) is as | 算術、邏輯、位元、比較、移位、合併、null 合併、型別測試 |
| 三元運算子 | 3 | 中置雙符號 | a ? b : c | 條件運算子 (唯一) |
一元運算子深度解析
前綴 vs 後綴 (遞增遞減)
int x = 5;
++x; // 前綴:先修改,值為新值 (6)
x++; // 後綴:先取值,再修改,值為舊值 (5)
// 優先級差異:後綴屬主要運算子 (最高),前綴屬一元運算子
x++ * 2 // (x++) * 2
++x * 2 // (++x) * 2
算術一元運算子
+x // 一元正號:無作用 (僅為對稱性),回傳 x
-x // 一元負號:算術取反,溢位行為同減法
// 整數:MinValue 取負溢位 (環繞/例外)
// 浮點數:精確翻轉符號位,-0.0 → +0.0
邏輯/位元一元運算子
!x // 邏輯非:bool 翻轉,短路不適用 (單運算元)
~x // 位元補數:逐位翻轉,整數類型
// ~5 (0101) = -6 (1010 補數表示)
轉型運算子
(T)x // 強制轉型:編譯時期/執行時期檢查
// 隱含轉換無需括號:long l = 5;
// 顯式轉換需括號:int i = (int)l;
型別查詢運算子 (編譯期/執行期)
typeof(T) // 編譯期:回傳 System.Type,無執行開銷
sizeof(T) // 編譯期:非受控類型大小 (位元組),需 unsafe
nameof(x) // 編譯期:變數/型別/成員名稱字串,重構安全
default(T) // 編譯期/執行期:型別預設值 (C# 7.1+ 可省略 T)
非同步/參考運算子
await x // 非同步等待:暫停方法,續行於 awaitable 完成
ref x // 參考傳遞/回傳:別名語意,非複製
out x // 輸出參數:必須在方法內指派
二元運算子深度解析
算術運算子 (支援多載)
a + b // 加法:數值、字串、委派、TimeSpan、列舉+基底
a - b // 減法:數值、委派移除、TimeSpan/DateTime、列舉-基底/列舉
a * b // 乘法:數值
a / b // 除法:數值
a % b // 餘數:整數、浮點數、decimal
移位運算子
a << b // 左移:低位補 0,高位捨棄,等價 ×2^b
a >> b // 右移:有號算術位移 (符號位擴展),無號邏輯位移 (補 0)
比較運算子
a == b // 等值:所有類型 (參考類型預設參考比較)
a != b // 不等值
a < b // 小於:數值、列舉、IComparable
a > b // 大於
a <= b // 小於等於
a >= b // 大於等於
邏輯運算子 (位元 vs 條件)
| 運算子 | 類型 | 短路 | 適用類型 | 多載 |
& | 位元 AND / 邏輯 AND | 否 | 整數、bool、enum | 是 |
| | 位元 OR / 邏輯 OR | 否 | 整數、bool、enum | 是 |
^ | 位元 XOR / 邏輯 XOR | 否 | 整數、bool、enum | 是 |
&& | 條件 AND | 是 | bool | 間接 (true/false + &/|) |
|| | 條件 OR | 是 | bool | 間接 (true/false + &/|) |
特殊二元運算子
a ?? b // Null 合併:a 為 null 才評估 b (短路)
a ? b : c // 條件運算子 (三元,但語法為二元形式)
is T // 型別模式比對:回傳 bool,支援宣告模式
as T // 安全參考轉型:失敗回傳 null,不拋出例外
// 字串/委派專用
s1 + s2 // 字串串接
d1 + d2 // 委派合併
d1 - d2 // 委派移除
三元運算子:條件運算子 (唯一)
a ? b : c
// 語意:評估 a (bool),真 → 評估 b 回傳,假 → 評估 c 回傳
// 短路:只評估其中一分支
// 右結合:a ? b : c ? d : e → a ? b : (c ? d : e)
// 類型推斷:依 b、c 型別推導結果型別 (隱含轉換規則)
特殊運算子:關鍵字形式與語法糖
| 運算子 | 形式 | 功能 | 分類 |
new | 關鍵字 | 物件/陣列/委派建立 | 物件建立表達式 |
typeof | 關鍵字 | 編譯期型別資訊 | 型別查詢 |
sizeof | 關鍵字 | 非受控類型大小 | 型別查詢 |
checked | 關鍵字/區塊 | 啟用溢位檢查 | 檢查語境 |
unchecked | 關鍵字/區塊 | 停用溢位檢查 | 檢查語境 |
default | 關鍵字/運算式 | 型別預設值 | 字面值 |
nameof | 關鍵字 | 符號名稱字串 | 編譯期常數 |
stackalloc | 關鍵字 | 堆疊配置記憶體 | 記憶體管理 |
=> | 符號 | Lambda / 運算式主體 / switch 運算式 | 函數式語法糖 |
? | 後綴/前綴 | 可為 null 型別標記 / null 條件運算子 | 型別系統 / 短路存取 |
運算子多載與使用者定義型別
public readonly struct Complex
{
public double Re, Im;
// 二元運算子多載
public static Complex operator +(Complex a, Complex b)
=> new Complex { Re = a.Re + b.Re, Im = a.Im + b.Im };
// 一元運算子多載
public static Complex operator -(Complex a)
=> new Complex { Re = -a.Re, Im = -a.Im };
// 比較運算子必須成對多載
public static bool operator ==(Complex a, Complex b)
=> a.Re == b.Re && a.Im == b.Im;
public static bool operator !=(Complex a, Complex b) => !(a == b);
// 隱含/顯式轉換
public static implicit operator Complex(double d)
=> new Complex { Re = d, Im = 0 };
public static explicit operator double(Complex c)
=> Math.Sqrt(c.Re * c.Re + c.Im * c.Im); // 模長
}
現代 C# 語法糖演進
// C# 6.0
nameof(x) // 重構安全符號名稱
x?.y // Null 條件存取
x ?? y // Null 合併
// C# 7.0
x is T t // 型別模式宣告
(x, y) = (y, x) // 元組解構
// C# 8.0
x ??= y // Null 合併指派
switch (x) { case T t: ... } // Switch 運算式
// C# 9.0
x is not null // 否定模式
x is >= 0 and <= 10 // 關係/邏輯模式
with { Prop = v } // Record 不可變更新
// C# 10.0
$"{x} {y}" // 插值字串處理器優化
// C# 11.0
[1, 2, 3] // List 模式 / 集合運算式
raw"""...""" // 原始字串常值
快速識別指南:運算子 vs 關鍵字 vs 標點
- 運算子:參與運算式計算,有優先級、結合性、可多載 (部分) —
+, &&, ??, =>
- 關鍵字運算子:關鍵字形式但參與運算式 —
new, typeof, sizeof, checked, default, nameof, await, stackalloc
- 標點/分隔符:不參與計算,結構用途 —
;, ,, ., (), [], {}, : (標籤/三元/屬性)
系統性掌握運算子分類與語法特徵,能快速解析複雜運算式、正確應用優先級規則、善用現代語法糖提升表達力與安全性。