關係運算子是程式決策的基石,C# 提供豐富的比較運算子與類型測試運算子 (is, as),並針對不同類型 (數值、字串、列舉、參考、委派) 定義精確語意。
六大比較運算子
| 運算子 | 說明 | 適用類型 |
== | 等於 | 所有類型 |
!= | 不等於 | 所有類型 |
< | 小於 | 數值、列舉、可比較類型 |
> | 大於 | 數值、列舉、可比較類型 |
<= | 小於或等於 | 數值、列舉、可比較類型 |
>= | 大於或等於 | 數值、列舉、可比較類型 |
關係運算式特性
- 結果型別永遠為
bool
- 優先級:低於算術運算子,高於指派運算子
- 可鏈結:
(a > b) > (c < d) (但不建議,易混淆)
- 可作為布林值指派:
bool flag = a > b;
is 運算子:型別模式比對 (C# 7.0+ 增強)
基本型別檢查
Console.WriteLine(1 is int); // True
Console.WriteLine(1 is float); // False
Console.WriteLine(1.0 is float); // False
Console.WriteLine(1.0 is double); // True
型別模式與變數宣告 (C# 7.0+)
object obj = "Hello";
// 傳統寫法
if (obj is string)
{
string s = (string)obj;
Console.WriteLine(s.Length);
}
// 現代寫法:宣告模式
if (obj is string s) // 直接宣告並轉型
{
Console.WriteLine(s.Length);
}
// 常數模式
if (obj is "Hello") // C# 9.0+ 比對常數值
{
Console.WriteLine("匹配");
}
// 型別範圍檢查
if (obj is not null) // C# 9.0+ 否定模式
{
// ...
}
進階模式比對 (C# 9.0+)
// 關係模式
if (number is >= 0 and <= 100) { ... }
// 邏輯模式組合
if (input is string { Length: > 0 } or int > 0) { ... }
// switch 運算式中的模式
var result = obj switch
{
int i => i * 2,
string s => s.Length,
null => 0,
_ => -1
};
as 運算子:安全參考轉型
核心語意
運算式 as 目標類型
// 成功:回傳轉型後的參考
// 失敗:回傳 null (不拋出例外)
// 限制:僅限參考類型、可為 null 的值類型、介面轉型
與強制轉型對比
| 場景 | (T)obj | obj as T |
| 轉型成功 | 回傳 T | 回傳 T |
| 轉型失敗 (參考類型) | 拋出 InvalidCastException | 回傳 null |
| 值類型轉型 | 支援 (拆箱) | 不支援 (編譯錯誤) |
| 使用者定義轉型 | 支援 | 不支援 |
| 適用場景 | 確定轉型會成功 | 不確定、預期可能失敗 |
實戰範例
object[] items = { "text", 123, DateTime.Now, null };
foreach (var item in items)
{
// 安全轉型 + null 檢查
if (item is string s)
{
Console.WriteLine($"字串: {s.ToUpper()}");
}
else if (item is DateTime dt)
{
Console.WriteLine($"日期: {dt:yyyy-MM-dd}");
}
// as 適用:介面轉型
if (item is IDisposable disp)
{
// 使用介面...
}
}
// 經典 as 用法:事件處理器
void OnClick(object sender, EventArgs e)
{
var btn = sender as Button;
if (btn != null) btn.BackColor = Color.Red;
}
各類型比較語意細節
數值類型 (IEEE 754)
NaN 比較:NaN == NaN → false,NaN != NaN → true
+0.0 == -0.0 → true
- 無窮大:
-∞ < 任何有限值 < +∞
布林類型
- 僅支援
==, !=
false < true (隱含轉換為 0/1)
!= 等價於 ^ (XOR)
列舉類型
- 隱含支援所有六大比較運算子
- 比較底層整數值:
(U)x op (U)y
字串比較 (重點)
| 運算子 | 比較語意 | 注意事項 |
==, != | 序數比較 (序數忽略大小寫? 不,預設區分大小寫) | 比較值,非參考 |
<, > 等 | 不支援 (編譯錯誤) | 使用 string.Compare |
// 值比較
"hello" == "hello" // true
"hello" == "HELLO" // false (區分大小寫)
string s1 = "he" + "llo";
string s2 = "hello";
s1 == s2 // true (不同實例,同值)
// 參考比較 (需明確)
object.ReferenceEquals(s1, s2) // false
委派比較
- 支援
==, !=
- 比較調用清單是否相同 (多播委派逐個比對)
最佳實踐總結
- 型別檢查優先用
is — 安全、可讀、支援模式比對
- 參考轉型不確定時用
as — 避免例外開銷,配合 null 檢查
- 字串比較用
== — 值語意,效能佳 (內建驻留優化)
- 避免
as 用於值類型 — 編譯錯誤,改用 is + 轉型或 Nullable<T>
- 自訂類型實作
IComparable<T> — 獲得標準比較支援
善用 is/as 與模式比對,能編寫更安全、簡潔且現代化的類型處理程式碼。