using 與 as 是 C# 中兩個極具實用價值卻常被忽略的語法特性。前者確保資源確定性釋放,後者提供安全的型別轉換。善用它們能寫出更健壯、可讀性更高的程式碼。
using 定義一個範圍,範圍結束時自動呼叫物件的 Dispose() 方法(需實作 IDisposable 介面)。編譯器會將其轉換為 try/finally 區塊。
// 自訂實作 IDisposable 的類別
public class TestResource : IDisposable
{
public void Dispose()
{
Console.WriteLine("Dispose - 資源已釋放");
}
public void DoWork()
{
Console.WriteLine("Do a method - 執行工作");
}
}
// 使用 using 區塊
using (TestResource resource = new TestResource())
{
resource.DoWork();
}
// 輸出順序:
// Do a method - 執行工作
// Dispose - 資源已釋放
SqlConnection、OracleConnection)FileStream、StreamReader、StreamWriter)Graphics、Bitmap、Pen、Brush)TcpClient、HttpWebResponse)IDisposable 的非託管資源包裝類別// 巢狀寫法
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(sql, conn))
using (var reader = cmd.ExecuteReader())
{
// ...
}
// C# 8.0+ using 宣告(無需大括號,範圍至方法結束)
using var conn = new SqlConnection(connStr);
using var cmd = new SqlCommand(sql, conn);
expression as type
// 等價於
expression is type ? (type)expression : (type)null
關鍵差異:轉換失敗時 回傳 null 而非拋出例外。as 僅適用於參考型別與裝箱轉換,值型別(如 int、double)不可使用(除非是可為 null 的值型別 int?)。
object[] items = { 123, "test", DateTime.Now, 45.6 };
// ❌ 直接轉型:失敗拋例外
foreach (object o in items)
{
string s = (string)o; // 第 1、3、4 項會拋 InvalidCastException
Console.WriteLine(s);
}
// ✅ 使用 as:失敗回傳 null,配合 null 檢查
for (int i = 0; i < items.Length; i++)
{
string s = items[i] as string;
if (s != null)
Console.WriteLine($"{i}: {s}"); // 僅輸出 "1: test"
}
// 傳統寫法
var obj = GetObject();
string str = obj as string;
if (str != null) { /* 使用 str */ }
// 模式比對更簡潔
if (obj is string s)
{
// 直接使用 s
}
// 甚至可用於 switch
switch (obj)
{
case string s: /* ... */ break;
case int i: /* ... */ break;
case null: /* ... */ break;
}
| 特性 | using | as |
|---|---|---|
| 核心目的 | 資源確定性釋放 | 安全型別轉換 |
| 適用對象 | IDisposable 物件 | 參考型別 / 可為 null 值型別 |
| 失敗行為 | N/A(編譯期保證) | 回傳 null |
| 常見錯誤 | 忘記 using 導致資源洩漏 | 用於值型別、忽略 null 檢查 |
將 using 與 as 內化為編碼習慣,能顯著減少資源洩漏與型別轉換例外,是邁向 C# 專業開發者的關鍵步驟。