try-catch-finally 是 .NET 異常處理基石,using 則是針對 IDisposable 資源的語法糖。本文透過 IL 反編譯驗證兩者等價性,並探討異常情境下的資源釋放保證與程式碼片段優化。
finally 區塊無論 try 正常結束或拋出異常都會執行,適用於非託管資源釋放。常見模式:
try-catch:捕獲處理異常try-finally:確保清理碼執行try-catch-finally:完整異常處理與清理以 Font 為例,using 區塊編譯後的 IL 顯式包含 .try / finally 區塊,在 finally 中判斷物件非 null 後呼叫 Dispose()。手寫 try-finally 產生的 IL 幾乎完全一致,證明 using 純屬編譯器語法糖。
編譯器會將 try-catch-finally 拆解為巢狀結構:外層 try-finally,內層 try-catch。這意味著 catch 先執行,再進入 finally,符合預期語意。
若 using 區塊內拋出異常(如 Int32.Parse("a")),Dispose() 仍會在 finally 中正常執行,但未處理的異常會導致程式終止並顯示不友善錯誤視窗。
為同時享有 using 簡潔性與異常捕獲,自訂 usingTry Code Snippet:
<CodeSnippet Format="1.0.0">
<Header>
<Title>usingTry</Title>
<Shortcut>usingTry</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal><ID>resource</ID><Default>resource</Default></Literal>
<Literal><ID>expression</ID><Function>SimpleTypeName(global::System.Exception)</Function></Literal>
</Declarations>
<Code Language="csharp"><![CDATA[
using($resource$)
{
try { $selected$ }
catch ($expression$) { $end$ }
}
]]></Code>
</Snippet>
</CodeSnippet>
使用方式同 using,輸入 usingTry 按 Tab 即可產生含 try-catch 的 using 區塊,編譯效果等同 try-catch-finally 但程式碼更精簡。