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

C# is 與 as 運算子完全指南:型別檢查與安全轉型的最佳實踐

     編輯:關於C#

前言:型別系統的兩把瑞士刀

在 C# 的型別系統中,is 與 as 是處理多型與型別轉換最核心的兩個運算子。本文將從語法規則、IL 層面、效能考量到實戰模式,全方位剖析兩者的異同與最佳用法。

一、is 運算子:型別相容性檢查

基本語法與行為

expression is type
  • 回傳 bool:true 表示表達式非 null 且可安全轉換為指定型別;false 表示 null 或轉換會拋例外。
  • 僅考慮參考轉換、裝箱轉換、取消裝箱轉換。
  • 不支援使用者定義轉換、數值型別間的隱式轉換。

邊界情況

情況結果說明
表達式為 nullfalse無物件可驗證,不拋例外
型別不相容false如 new object() is string
值型別檢查編譯錯誤int i=5; i is decimal → CS0184「運算式永遠是 false」

限制

  • 不可多載。
  • 第一個運算元不能是 lambda/匿名方法(CS1977)。

二、as 運算子:安全參考轉換

基本語法與行為

expression as type
  • 相容時回傳轉換後的參考;不相容或 null 時回傳 null,永不拋例外。
  • 等價邏輯:expr is type ? (type)expr : (type)null。
  • 同樣僅支援參考/裝箱/取消裝箱轉換。

經典錯誤:嘗試轉換值型別

object o = 5;
int i = o as int; // 編譯錯誤 CS0039:值型別不可為 null
// 正確寫法
int? i = o as int?; // 可為 null 的值型別
int i = (int)o;     // 直接轉型(可能拋 InvalidCastException)

三、IL 層面揭秘:isinst 指令的雙重身分

編譯下列程式並觀察 IL:

object o = new Student();
bool b = o is Student;   // IL: isinst Student → ldnull → cgt.un
Student s = o as Student; // IL: isinst Student → stloc.1

兩者核心皆呼叫 isinst 指令(測試物件是否為特定類別實例):

  • is:isinst 結果與 null 比較(cgt.un),產生 bool。
  • as:直接儲存 isinst 結果(可能為 null)。

這證明 as 本質上是 is 的語法糖,零額外開銷。

四、模式比較(C# 7+):is 型別模式的現代寫法

// 傳統寫法
if (obj is Student s)
{
    s.Study();
}

// C# 7+ 型別模式(更簡潔,變數作用域限於區塊內)
if (obj is Student student)
{
    student.Study();
}

// switch 表達式搭配 (C# 8+)
var msg = obj switch
{
    Student s => $"{s.Name} 正在讀書",
    Teacher t => $"{t.Name} 正在教學",
    _ => "未知角色"
};

五、效能與最佳實踐

場景建議理由
僅需檢查型別is語意清晰,回傳 bool
檢查後立即使用is 型別模式單次轉換,變數作用域最小化
舊版本需檢查後使用as + null 檢查避免雙重轉換(is + cast)
高效能熱路徑兩者皆可IL 相同,JIT 優化後無差異
值型別轉換直接轉型或 Nullableas 不支援非 nullable 值型別

六、常見陷阱

  1. as 後忘記 null 檢查:導致後續 NullReferenceException,錯誤位置遠離根因。
  2. 混用 is + cast:if (o is Student) ((Student)o).Study(); 進行兩次型別檢查(雖 JIT 可能優化)。
  3. 介面轉換誤用 as:obj as IInterface 若物件實作介面但非參考轉換(如結構體實作介面會裝箱),行為正確但需理解裝箱成本。

總結

is 是「詢問」,as 是「嘗試」。現代 C# 應優先使用 is 型別模式,兼顧安全、可讀與效能。理解底層 isinst 機制,能在除錯與效能調優時游刃有餘。

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