using 與 as 是 C# 兩大實用語法糖,分別解決資源確定性釋放與安全型別轉換問題。本文詳細說明用法、IL 機制、最佳實踐與常見誤區。
// 完整形式
using (ResourceType resource = new ResourceType())
{
resource.DoWork();
} // 隱含 try/finally,保證呼叫 Dispose()
// C# 8.0+ using 宣告 (範圍至區塊結束)
using var resource = new ResourceType();
resource.DoWork();
// 區塊結束自動 Dispose
// 原始碼
using (var r = new Resource()) { r.Work(); }
// 等價展開
Resource r = new Resource();
try
{
r.Work();
}
finally
{
if (r != null)
((IDisposable)r).Dispose();
}
public class TestUsing : IDisposable
{
private bool _disposed = false;
public void DoWork() => Console.WriteLine("Do a method");
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 釋放託管資源
Console.WriteLine("Dispose managed");
}
// 釋放非託管資源
Console.WriteLine("Dispose unmanaged");
_disposed = true;
}
}
~TestUsing() => Dispose(false); // 終結器備援
}
FileStream, StreamReader/Writer)SqlConnection)Graphics, Bitmap)HttpClient, TcpClient)IDisposable 的物件
// as 運算子
string s = obj as string;
// 等價於
string s = (obj is string) ? (string)obj : null;
// 差異:as 只評估 obj 一次,is+cast 評估兩次
// ✅ 參考型別:類別、介面、陣列、委派、string
object obj = "hello";
string s = obj as string; // 合法
// ❌ 值型別:int、struct、enum、DateTime
object val = 123;
// int i = val as int; // 編譯錯誤 CS0039
// ✅ 可為 null 的值型別
int? nullable = 123;
int? result = nullable as int?; // 合法 (int? 是參考型別包裝)
object[] items = { 123, "hello", 45.6, "world", DateTime.Now };
// 傳統寫法:try-catch 或 is+cast
foreach (object item in items)
{
if (item is string s) // C# 7+ 模式比對
Console.WriteLine($"String: {s}");
}
// as 寫法 (C# 6 或偏好風格)
foreach (object item in items)
{
string s = item as string;
if (s != null)
Console.WriteLine($"String: {s}");
}
| 特性 | using | as |
|---|---|---|
| 目的 | 資源生命週期管理 | 安全型別轉換 |
| 適用對象 | IDisposable 實作類別 | 參考型別轉換 |
| 失敗行為 | 編譯期錯誤 (未實作 IDisposable) | 回傳 null (不拋出例外) |
| 語法糖本質 | try/finally + Dispose() | is 檢查 + 條件轉換 |
| C# 8 新語法 | using 宣告 | — |
| 誤區 | 正確認知 |
|---|---|
| using 適用於所有物件 | 僅限實作 IDisposable 的型別 |
| as 可用於 int、double 等值型別 | 僅限參考型別;值型別用 nullable 或模式比對 |
| as 轉換失敗拋出例外 | 回傳 null,不拋出例外 |
| using 區塊內拋出例外不會 Dispose | finally 保證執行 Dispose,即使有例外 |
| as 比 is+cast 慢 | as 只評估一次,理論略快或持平 |
// IAsyncDisposable (C# 8+)
await using var stream = new FileStream("test.txt", FileMode.Create);
await stream.WriteAsync(buffer);
// 非同步資源需 await using,否則 Dispose 可能在資料寫入完成前執行
using 確保資源確定性釋放,是 IDisposable 模式的語法支柱;as 提供安全參考轉換,避免 InvalidCastException。兩者皆為 C# 語言層面的安全性保障,熟練掌握能寫出更健壯、可讀性更高的程式碼。