C# 複合指派 x op= y 處理邏輯:
x op yx 型別 → x = x op y(x 僅評估一次)x 型別,且 y 可隱含轉換為 x 型別(或為位移運算子)→ x = (T)(x op y)(T 為 x 型別)x op= y合法 ⇔x op y合法 且x = y合法
即:二元運算可執行、且結果可指派回左運算元。
byte b = 0;
char ch = '\0';
int i = 0;
b += 1; // OK: b = (byte)(b + 1)
b += 1000; // CS0266: b = 1000 不合法
b += i; // CS0266: b = i 不合法
b += (byte)i; // OK: 顯式轉換
ch += 1; // CS0266: ch = 1 不合法
ch += (char)1; // OK
| 特性 | C# | Java |
|---|---|---|
byte += int | 編譯錯誤(需顯式轉換) | 編譯通過,執行時截斷 |
String += Object | 合法(Object.ToString()) | JLS 曾限制,後開放 Object += String |
| 型別安全 | 編譯期強制 | 執行期截斷風險 |
| 使用者定義運算子 | 支援多載 +、+= 自動套用 | 無運算子多載 |
public event EventHandler MyEvent;
MyEvent += Handler; // 呼叫 add 存取子
MyEvent -= Handler; // 呼叫 remove 存取子
此時 += 不產生值,僅能用於陳述式脈絡。
public struct Vector2
{
public float X, Y;
public static Vector2 operator +(Vector2 a, Vector2 b)
=> new Vector2 { X = a.X + b.X, Y = a.Y + b.Y };
}
// 使用
var v1 = new Vector2 { X = 1, Y = 2 };
var v2 = new Vector2 { X = 3, Y = 4 };
v1 += v2; // 編譯器自動轉為 v1 = v1 + v2
| 陷阱 | 說明 | 對策 |
|---|---|---|
| 整數溢位 | byte b = 255; b += 1; 在 unchecked 內回繞為 0 | 關鍵計算用 checked 區塊或 int 運算 |
| 事件重複訂閱 | btn.Click += Handler 執行兩次 → Handler 被呼叫兩次 | 訂閱前先 -= 或用旗標控制 |
| 委派結合誤解 | d1 += d2 建立新委派,d1 原參考不變 | 理解委派不可變特性 |
C# += 設計嚴謹:編譯期保證型別安全、支援使用者定義運算子、事件語意清晰。開發者只需記住「x op y 與 x = y 皆合法才合法」即可避開大多數陷阱。從 Java 轉 C# 時,請拋棄「執行期自動截斷」的假設,擁抱編譯期強型別檢查。