as:安全型別轉換與模式比對的核心運算子as 是 C# 最常用的安全轉型運算子as 運算子嘗試將運算式轉換為指定參考型別(或可為 null 的實值型別),成功回傳轉換後的參考,失敗回傳 null,**永不拋出例外**。這使其成為「試探性轉型」的首選工具,廣泛用於事件處理器、工廠模式、訪問者模式、模式比對預處理等場景。
expression as Type
expression:任意運算式(參考型別、可為 null 實值型別、dynamic)。Type:參考型別(class/interface/delegate/array)或 Nullable<T>(int? 等)。Type(若 Type 為非可為 null 參考型別,結果仍為可為 null)。| 規則 | 說明 |
|---|---|
| 僅限參考轉換/裝箱/解箱/可為 null 轉換 | 不可用於使用者定義轉換、數值型別間轉換(如 int as long 編譯錯誤 CS0039) |
| 不執行使用者定義轉換運算子 | 僅考慮 CLR 內建參考/裝箱/可為 null 轉換 |
| 編譯期型別檢查 | 若 expression 編譯期型別與 Type 無繼承/實作關係 → 編譯錯誤 CS0039 |
| 執行期語意 | 等同 expression is Type ? (Type)expression : (Type)null(但只評估一次) |
| 不可用於非可為 null 實值型別 | int i = 5; var x = i as int; → 錯誤,需 int? |
void OnClick(object sender, EventArgs e) {
if (sender is Button btn) { btn.BackColor = Color.Red; } // C# 7+ 模式比對(推薦)
// 或舊版
var btn = sender as Button;
if (btn != null) btn.BackColor = Color.Red;
}
ICommand CreateCommand(object input) {
return input switch {
string s => new StringCommand(s),
int i => new IntCommand(i),
_ => throw new ArgumentException("Unsupported input type")
};
}
// 使用 as 進行前置檢查
if (input is not null && input as IValidatable is { } validatable) {
validatable.Validate();
}
// 不佳:兩次型別檢查
if (obj is MyClass) {
var mc = (MyClass)obj; // 再次驗證
mc.DoWork();
}
// 良好:as 單次檢查
var mc = obj as MyClass;
if (mc != null) mc.DoWork();
// 最佳(C# 7+):模式比對合併宣告與檢查
if (obj is MyClass mc2) mc2.DoWork();
var disposable = resource as IDisposable;
disposable?.Dispose(); // 安全呼叫,若非 IDisposable 則無操作
object[] arr = new string[10];
var stringArr = arr as string[]; // 成功(陣列協變性)
var intArr = arr as int[]; // null(執行期型別不符)
as vs is vs 強制轉型 (Type)| 運算子 | 成功結果 | 失敗結果 | 適用場景 |
|---|---|---|---|
as | 轉換後參考 | null | 不確定是否可轉換、預期失敗為正常流程 |
is (C# 7+ 模式) | true + 宣告變數 | false | 型別檢查+立即使用、模式比對 |
(Type) | 轉換後參考 | 拋出 InvalidCastException | 確信可轉換、失敗屬於程式錯誤 |
as 與 is 皆為單一指令(isinst),極度輕量。try/catch 包裹強制轉型(例外處理開銷巨大)。is 模式比對(編譯器優化最佳)。as 與 null 條件運算子 ?. 組合
var length = (obj as string)?.Length; // 若 obj 非 string → null,不拋出例外
var disposed = (resource as IDisposable)?.Dispose(); // 安全釋放
C# 關鍵字分為保留關鍵字(不可作識別碼)與內容關鍵字(特定語境有特殊意義,可作識別碼)。若需使用保留關鍵字作識別碼,加 @ 前綴(@class、@as)。
| 類別 | 關鍵字 |
|---|---|
| 型別 | bool byte char decimal double enum float int long sbyte short string uint ulong ushort object void |
| 修飾符 | abstract async const extern new override partial readonly sealed static unsafe virtual volatile |
| 流程控制 | break continue do else for foreach goto if return switch try catch finally throw lock using checked unchecked |
| 存取/命名空間 | public private protected internal namespace using |
| 類別/結構/介面 | class struct interface delegate event enum |
| 泛型 | where in out default |
| 非同步/迭代器 | async await yield |
| 查詢運算式 (LINQ) | from where select group orderby join into let ascending descending by on equals |
| 其他 | as is typeof nameof sizeof stackalloc ref out in params this base null true false operator implicit explicit |
as 運算子以「失敗回傳 null、不拋例外」的安全語意,成為 C# 型別系統中不可或缺的防禦性程式設計工具。配合 is 模式比對、?. null 條件運算子、?? null 聯合運算子,構成現代 C# 空值安全與型別安全的核心防線。掌握 as 的適用邊界(僅參考/裝箱/可為 null 轉換)、避免濫用於確定可轉換場景(改用強制轉型表達意圖),即能寫出更健壯、可讀性更高的程式碼。