is 運算子是 C# 型別系統的核心檢查工具,從簡單的型別相容性測試演進為強大的模式比對引擎 (C# 7.0+)。它不執行轉型,只回傳 bool,零副作用,是防禦性程式設計的首選。
運算式 is 目標類型 // 檢查:運算式結果是否可透過參考/裝箱/拆箱轉型為目標類型 // 回傳:true / false (從不拋出例外) // 運算式可為 null (null is T → false)
Console.WriteLine(1 is int); // True (int 相容 int)
Console.WriteLine(1 is float); // False (int 不隱含轉型為 float)
Console.WriteLine(1.0 is float); // False (double 不隱含轉型為 float)
Console.WriteLine(1.0 is double); // True (double 相容 double)
Console.WriteLine("text" is object); // True (字串繼承 object)
Console.WriteLine(null is string); // False (null 不相容任何實值型別)
if (obj is string)
{
string s = (string)obj; // 需額外強制轉型
Console.WriteLine(s.Length);
}
// 宣告模式:檢查成功直接宣告強型別變數
if (obj is string s)
{
Console.WriteLine(s.Length); // s 範圍限定在 if 區塊
}
// 範圍:s 僅在 is 為 true 的分支有效
// 外部無法存取 s (編譯器保證)
// 關係模式
if (number is >= 0 and <= 100) { ... }
// 邏輯模式組合
if (input is string { Length: > 0 } or int > 0) { ... }
// 否定模式
if (obj is not null) { ... } // 等價於 !(obj is null)
// 常數模式
if (status is 200 or 201) { ... } // 比對具體值
// var 模式 (永遠匹配,引入變數)
if (obj is var x) { ... } // 等價於 var x = obj;
int[] numbers = { 1, 2, 3, 4, 5 };
// 陣列長度與元素模式
if (numbers is [1, 2, .., 5]) { ... } // 開頭 1,2 結尾 5,中間任意
if (numbers is [_, _, 3, ..]) { ... } // 第三個元素為 3
// 切片模式
if (numbers is [.., > 0]) { ... } // 最後一個元素 > 0
record Person(string Name, int Age);
var person = new Person("Alice", 30);
// 屬性模式
if (person is { Age: >= 18, Name: "Alice" }) { ... }
// 型別模式結合屬性
if (person is Person { Age: > 65 } senior) { ... }
// 解構模式 (需 Deconstruct 方法)
if (person is (string name, int age)) { ... } // 自動解構
// 傳統 switch (C# 7.0)
switch (shape)
{
case Circle c: return c.Radius * c.Radius * Math.PI;
case Rectangle r: return r.Width * r.Height;
case null: return 0;
default: throw new ArgumentException();
}
// 現代 switch 運算式 (C# 8.0+) — 更簡潔、運算式導向
double Area(Shape shape) => shape switch
{
Circle { Radius: var r } => r * r * Math.PI,
Rectangle { Width: var w, Height: var h } => w * h,
Triangle { Base: var b, Height: var h } => 0.5 * b * h,
null => 0,
_ => throw new ArgumentException($"未知形狀: {shape}")
};
| 需求 | 推薦方案 | 理由 |
|---|---|---|
| 僅檢查型別 | is T | 零成本、無副作用、語意清晰 |
| 檢查並使用轉型後值 | is T var (C# 7+) | 單次檢查、變數範圍安全、無 null 風險 |
| 參考轉型,失敗預期為 null | as T + null 檢查 | 舊版相容、介面轉型常用 |
| 確定轉型必成功 | (T)obj | 失敗即 Bug,拋出例外暴露問題 |
| 複雜多條件分派 | switch 運算式 | 窮盡性檢查、運算式導向、效能最佳 |
isinst + 分支指令 — 極快if (x is T t) 優於 var t = x as T; if (t != null)is not null 優於 != null (針對多載 == 的類型)if ((obj is string) == true) — 多餘括號與比較is 後緊接強制轉型 — if (obj is string) { var s = (string)obj; } → 改用 if (obj is string s)is not null — 明確語意、避開運算子多載陷阱is 運算子從簡單的型別檢查進化為模式比對核心,掌握其現代語法能編寫更安全、簡潔且具表達力的型別處理邏輯。