| 特性 | as | is |
|---|---|---|
| 用途 | 安全參考型別轉換,失敗回傳 null | 型別相容性檢查,回傳 bool |
| 適用型別 | 參考型別、可為 null 的實值型別、介面 | 所有型別 (含實值型別、Tuple、模式比對) |
| 失敗行為 | 回傳 null,不拋例外 | 回傳 false |
| C# 7+ 新功能 | 無重大變更 | 支援 型別模式 is Type var、常數模式、屬性模式 |
| 典型使用場景 | 「轉換成功才用,失敗忽略」 | 「先確認型別再處理」或 switch 表達式 |
as 運算子:安全轉換的語法糖// 這兩段完全等價 (expression 僅評估一次)
var result = expression as TargetType;
// 等價於
var temp = expression;
var result = (temp is TargetType) ? (TargetType)temp : (TargetType)null;
int i = obj as int; // 編譯錯誤,需改 int? i = obj as int?。operator 不會被 as 呼叫,必須用強制轉換 (TargetType)obj。object boxed = 123; int? v = boxed as int?; // null (拆箱失敗),需先 is int 再 (int)boxed。// ❌ 舊寫法:兩次型別檢查 (is + as 隱含)
if (obj is DataRowView)
{
var row = obj as DataRowView; // 再檢查一次
Console.WriteLine(row["Name"]);
}
// ✅ 新寫法:型別模式單次檢查 + 宣告區域變數
if (obj is DataRowView row)
{
Console.WriteLine(row["Name"]);
}
// ✅ 更簡潔:switch 表達式 (C# 8+)
var desc = obj switch
{
DataRowView r => $"Row: {r["Name"]}",
DataTable t => $"Table: {t.TableName}",
_ => "Unknown"
};
is 運算子:從型別檢查到模式比對的進化if (obj is string) { /* ... */ }
if (obj is IEnumerable<int>) { /* ... */ } // 介面檢查
if (obj is null) { /* ... */ } // C# 7+ 常數模式,優於 obj == null
// 同時檢查型別並宣告強型別變數,作用域限於 if 區塊
if (sender is Button btn)
{
btn.Enabled = false; // btn 直接是 Button 型別,無需再轉換
}
// 結合條件模式 (when 子句)
if (obj is int count when count > 0)
{
Console.WriteLine($"Positive: {count}");
}
public string Format(object input) => input switch
{
// 型別模式 + 屬性模式
Person { Age: >= 18, Name: var n } => $"Adult: {n}",
Person { Age: < 18 } => "Minor",
// 陣列/清單模式 (C# 11+)
[var first, _, var last] => $"First: {first}, Last: {last}",
null => "Null",
_ => input.ToString()
};
obj is Type | 1x (基準) | 單一型別檢查指令 |
| obj as Type | ~1x | 內部同樣執行 isinst IL 指令 |
| (Type)obj | ~1x (成功) / 高 (失敗拋例外) | castclass 指令,失敗擲回 InvalidCastException (昂貴) |
| obj is Type t | 1x | 型別模式無額外成本,編譯器優化為單次檢查 |
結論:as、is、型別模式在成功路徑效能相近。真正差異在失敗路徑:as/is無例外開銷,強制轉換拋例外極慢。熱路徑嚴禁用強制轉換做型別檢查。
is Type var 型別模式:單次檢查、強型別變數、可讀性最高、支援 when 守衛。var t = obj as TargetType; if (t != null) ... 仍可接受,但型別模式 if (obj is TargetType t) 更現代。is + as 雙重檢查:舊碼 if (obj is T) { var t = obj as T; } 必須重構。switch 表達式 + 屬性模式,編譯器優化跳躍表,效能與維護性雙贏。object o = 123; if (o is int i) ... 唯一正解,as 無法拆箱。掌握 as/is 與模式比對的演進脈絡,能寫出更安全、高效、可讀的現代 C# 代碼。