首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

C# 運算子完整指南:算術/關係/邏輯/位元/指派/其他運算子、優先序與實戰技巧

     編輯:C# 入門

C# 運算子完整指南:算術/關係/邏輯/位元/指派/其他運算子、優先序與實戰技巧

運算子 是告訴編譯器執行特定運算的符號。C# 提供豐富的內建運算子,分為六大類。理解運算子語意、優先序、副作用、溢位行為,是寫出正確、高效程式碼的基礎。

運算子分類總覽

類別運算子說明
算術+ - * / %加減乘除取模
++ --遞增遞減 (前綴/後綴)
+ -一元正負號
關係== != < > <= >=相等/不等/大小比較
邏輯&& || !邏輯與/或/非 (短路)
& | ^位元與/或/異或 (非短路,也用於 bool)
位元~位元補數 (翻轉)
<< >>左移/右移
指派=簡單指派
+= -= *= /= %=複合指派
<<= >>= &= |= ^=位元複合指派
其他?. ?[] ?? ??=Null 條件/合併
?:三元條件
is as型別測試/轉換
sizeof typeof nameof大小/型別/名稱
new default delegate建立/預設/委派
-> =>Lambda/運算式主體

算術運算子細節

整數溢位行為

// 預設 unchecked context:溢位環繞 (不拋例外)
int max = int.MaxValue; // 2,147,483,647
var overflow = max + 1; // -2,147,483,648

// checked context:溢位拋 OverflowException
checked {
    var overflow2 = max + 1; // 擲出例外
}
// 或編譯器選項 /checked+

遞增遞減副作用

int a = 5;
int b = a++; // b=5, a=6 (後綴:先用後增)
int c = ++a; // c=7, a=7 (前綴:先增後用)

int d = 5;
int e = d--; // e=5, d=4
int f = --d; // f=3, d=3

除法與取模

int a = 7, b = 3;
a / b; // 2 (整數除法捨去小數)
a % b; // 1 (餘數)

// 負數取模:結果符號同被除數
-7 % 3;  // -1
7 % -3;  // 1
-7 % -3; // -1

關係運算子與比較

參考型別比較

string a = "hello", b = "hello";
a == b; // true (字串多載 == 比較內容)
object o1 = a, o2 = b;
o1 == o2; // true (字串仍比較內容)

var sb1 = new StringBuilder("x");
var sb2 = new StringBuilder("x");
sb1 == sb2; // false (預設參考比較,未多載 ==)

浮點數比較陷阱

double x = 0.1 + 0.2; // 0.30000000000000004
x == 0.3; // false!

// 正確:容差比較
bool AlmostEqual(double a, double b, double epsilon = 1e-10) 
    => Math.Abs(a - b) < epsilon;

邏輯運算子:短路求值

bool a = true, b = false;
a && b; // false (短路:b 不執行)
a || b; // true  (短路:b 不執行)

// 利用短路避免 NullReference
if (user != null && user.IsActive) { } // user 為 null 時不存取 IsActive

// 非短路版本 (& |) - 兩邊皆執行
if (user != null & user.IsActive) { } // 危險:user 為 null 仍存取 IsActive

位元運算子實戰

旗標操作

[Flags] enum Permissions { None=0, Read=1, Write=2, Execute=4, Admin=8 }

var p = Permissions.Read | Permissions.Write; // 3 (Read+Write)
p.HasFlag(Permissions.Read); // true

// 設定旗標
p |= Permissions.Execute; // 加入 Execute
// 移除旗標
p &= ~Permissions.Write;  // 移除 Write
// 切換旗標
p ^= Permissions.Admin;   // 反轉 Admin

位元技巧

// 2 的冪次檢查
bool IsPowerOfTwo(int n) => n > 0 && (n & (n - 1)) == 0;

// 取模優化 (2 的冪次)
int ModPowerOfTwo(int x, int m) => x & (m - 1); // m 必須是 2 的冪次

// 交換兩數 (無暫存變數)
a ^= b; b ^= a; a ^= b;

// 快速乘除 2
x << 1; // x * 2
x >> 1; // x / 2 (算術右移,保留符號)

指派運算子與複合指派

int x = 10;
x += 5;  // x = x + 5
x -= 3;  // x = x - 3
x *= 2;  // x = x * 2
x /= 4;  // x = x / 4
x %= 3;  // x = x % 3
x <<= 1; // x = x << 1
x &= 0xF; // x = x & 0xF

// 複合指派於屬性/索引子:只評估一次左邊
list[GetIndex()] += 1; // GetIndex() 只呼叫一次

Null 相關運算子

運算子名稱範例說明
?.Null 條件成員存取user?.Nameuser 為 null 回傳 null,否則存取 Name
?[]Null 條件索引arr?[0]arr 為 null 回傳 null
??Null 合併x ?? "default"x 為 null 回傳右邊
??=`Null 合併指派x ??= "default"x 為 null 才指派

其他重要運算子

is / as / ?:`

// 型別測試 + 模式比對
if (obj is int i) { }
if (obj is string { Length: > 5 }) { }

// 安全轉換
string s = obj as string; // 失敗回傳 null (僅參考型別)
// 等同
string s2 = obj is string str ? str : null;

// 三元運算子
var result = condition ? valueIfTrue : valueIfFalse;

sizeof / typeof / nameof

sizeof(int);        // 4 (編譯期常數,需 unsafe context 除非內建型別)
typeof(string);     // System.Type 物件
nameof(Console);    // "Console" (編譯期字串,重構安全)

運算子優先序與結合性

高優先序先執行。同優先序依結合性 (大多左結合,指派/一元/三元右結合)。

優先序 (高→低)運算子結合性
1x.y f(x) a[x] x++ x-- new typeof sizeof checked unchecked左
2+ - ! ~ ++x --x (T)x await右
3* / %左
4+ -左
5<< >>左
6< > <= >= is as左
7== !=左
8&左
9^左
10|左
11&&左
12||左
13?: ??右
14= += -= *= /= %= &= |= ^= <<= >>= ??=`右

實戰範例:優先序陷阱

int a = 10, b = 20, c = 30;

// 1. && 優先於 ||
bool r1 = a > 5 || b < 10 && c == 30; // a>5 (true) 短路 -> true

// 2. ?: 右結合
int r2 = a > b ? 1 : a > c ? 2 : 3; // a>b? 1 : (a>c? 2 : 3)

// 3. 指派右結合
int x, y, z;
x = y = z = 5; // x = (y = (z = 5))

// 4. 建議加括號提升可讀性
bool r3 = (a > 5) || ((b < 10) && (c == 30));

最佳實踐

  • 括號明確意圖:不確定優先序時加括號,維護者感謝你。
  • 短路邏輯防禦:obj != null && obj.Method() 習慣用法。
  • 避免副作用運算式:x = y++ + z++ 難閱讀,拆行。
  • 浮點數勿用 ==:用容差比較。
  • 位元旗標用 [Flags] enum:語意清晰、IDE 支援。
  • Null 運算子鏈:a?.b?.c ?? default 簡潔安全。

常見問題 FAQ

Q: a += b 等同 a = a + b 嗎?

A: 大多數情況是,但 a 為屬性/索引子時,+= 只評估一次左邊 (避免重複 getter/setter 呼叫)。

Q: && vs & 什麼時候用哪個?

A: 幾乎永遠用 && (短路)。& 用於位元運算、或罕見需兩邊副作用皆執行時。

Q: 右移 >> 是算術還是邏輯?

A: 有號整數為算術右移 (保留符號位),無號整數為邏輯右移 (補 0)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved