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

.NET 中 as 與 is 運算子深度解析:型別轉換、模式比對與效能抉擇

     編輯:ASP.NET 基礎

核心差異一覽

特性asis
用途安全參考型別轉換,失敗回傳 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;

限制條件

  • 不可用於不可為 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。

最佳實踐:轉換後立即使用 (C# 7+ 型別模式取代傳統寫法)

// ❌ 舊寫法:兩次型別檢查 (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

C# 7+ 型別模式:宣告模式

// 同時檢查型別並宣告強型別變數,作用域限於 if 區塊
if (sender is Button btn)
{
    btn.Enabled = false; // btn 直接是 Button 型別,無需再轉換
}

// 結合條件模式 (when 子句)
if (obj is int count when count > 0)
{
    Console.WriteLine($"Positive: {count}");
}

C# 8+ Switch 表達式與屬性模式:現代型別分派利器

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 無例外開銷,強制轉換拋例外極慢。熱路徑嚴禁用強制轉換做型別檢查。

實戰決策樹

```mermaid flowchart TD A[需要轉換並使用結果?] -->|是| B[能接受 null 結果?] A -->|否,只需判斷| C[用 is 型別模式 / switch 表達式] B -->|是| D[用 as 或 is 型別模式] B -->|否,必須成功| E[用強制轉換 (Type)obj + 契約/斷言] D --> F{目標是實值型別?} F -->|是| G[用 is Type t 或 as Type?] F -->|否| H[用 as Type 或 is Type t] ```

總結建議

  1. 預設使用 is Type var 型別模式:單次檢查、強型別變數、可讀性最高、支援 when 守衛。
  2. 需求為「轉換失敗回傳 null 繼續流程」:var t = obj as TargetType; if (t != null) ... 仍可接受,但型別模式 if (obj is TargetType t) 更現代。
  3. 避免 is + as 雙重檢查:舊碼 if (obj is T) { var t = obj as T; } 必須重構。
  4. 複雜多型分派:改用 switch 表達式 + 屬性模式,編譯器優化跳躍表,效能與維護性雙贏。
  5. 實值型別拆箱:object o = 123; if (o is int i) ... 唯一正解,as 無法拆箱。

掌握 as/is 與模式比對的演進脈絡,能寫出更安全、高效、可讀的現代 C# 代碼。

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