using 是 C# 中出現頻率最高的關鍵字之一,卻常被誤解為單一功能。實際上它有**三種截然不同的用法**:命名空間指令、別名指令、資源釋放語句。本文逐一深度解析語法、編譯行為、進階技巧與常見坑點。
using System; // 匯入 System 命名空間
using System.Collections.Generic; // 匯入巢狀命名空間
List<T> 而非 System.Collections.Generic.List<T>)。using System; **不會**自動匯入 System.IO、System.Text 等子命名空間。GlobalUsings.cs 或 <ImplicitUsings>enable</ImplicitUsings>) 宣告,全專案生效,減少重複。// 1. 為命名空間取別名
using ProjUtils = MyCompany.Project.Utilities;
// 2. 為型別取別名 (C# 12+ 支援 Tuple/指標等複雜型別)
using JsonNode = System.Text.Json.Nodes.JsonNode;
using IntMap = System.Collections.Generic.Dictionary<int, string>;
// 3. 解決同名型別衝突
using MyConfig = MyApp.Configuration.Settings;
using ThirdPartyConfig = ThirdPartyLib.Settings;
// 使用
var cfg = new MyConfig(); // 無歧義
using Alias = NamespaceOrType;using ILogger = Serilog.ILogger; 方便日後換套件)。base class、interface list、attribute 等型別位置 (需完整名稱)。// 標準寫法 (編譯器展開為 try/finally)
using (var fs = new FileStream("data.bin", FileMode.Open))
using (var reader = new BinaryReader(fs))
{
int value = reader.ReadInt32();
// ...
} // 此處自動呼叫 reader.Dispose() -> fs.Dispose()
// C# 8+ 簡化寫法 (範圍至區塊結尾)
using var fs = new FileStream("data.bin", FileMode.Open);
using var reader = new BinaryReader(fs);
// ... 方法結束時自動 Dispose
{
FileStream fs = new FileStream(...);
try
{
BinaryReader reader = new BinaryReader(fs);
try
{
// 使用區塊
}
finally
{
if (reader != null) ((IDisposable)reader).Dispose();
}
}
finally
{
if (fs != null) ((IDisposable)fs).Dispose();
}
}
finally 會檢查 null 再呼叫 Dispose(),安全。using 可疊加無大括號,編譯成巢狀 try/finally,確保**逆序釋放** (後建立先釋放)。using 宣告的變數為 readonly,不可重新指派。IDisposable 或 IAsyncDisposable 的型別 (C# 8+ await using)。| 特性 | using (var x = ...) { } (語句) | using var x = ...; (宣告) |
|---|---|---|
| 釋放時機 | 大括號結束時 | **變數作用域結束時** (通常是方法結束) |
| 程式碼縮排 | 增加一層 | **扁平化**,減少右移 |
| 早期釋放 | 離開區塊即釋放 | 需手動 { ... } 區塊或提前 return |
| 建議場景 | 資源生命週期短、邏輯區塊明確 | 資源伴隨方法生命週期、簡化程式碼 |
// 錯誤
var conn = new SqlConnection(cs);
conn.Open(); // 例外拋出時連線未關閉
// 正確
using var conn = new SqlConnection(cs);
conn.Open();
using (var ms = new MemoryStream())
{
var bytes = ms.ToArray();
}
var len = bytes.Length; // 正確:bytes 是 byte[] 非 IDisposable
// 錯誤
using (var reader = new StreamReader("a.txt"))
{
var line = reader.ReadLine();
}
Console.WriteLine(reader.EndOfStream); // CS0165 / ObjectDisposedException
// 標準 Dispose Pattern (含 Finalizer 保護非託管資源)
public class MyResource : IDisposable
{
private bool _disposed;
private IntPtr _handle; // 非託管資源
public void Dispose() => Dispose(true); // 公開方法
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// 釋放託管資源
}
// 釋放非託管資源
CloseHandle(_handle);
_handle = IntPtr.Zero;
_disposed = true;
}
~MyResource() => Dispose(false); // Finalizer
}
using var (C# 8+)**,程式碼更乾淨。<returns>呼叫端負責 Dispose</returns>。await using (C# 8+, IAsyncDisposable)。using 三重身分:
Dispose() 被呼叫,杜絕資源洩漏。掌握三者語法與編譯行為,善用 using var 與 await using,寫出**安全、乾淨、專業**的 C# 程式碼。