C# using()的本質

2022-09-01 21:03:48

「 程式世界沒有祕密,所有答案都在原始碼裡 」 

  

01.點明觀點 

C#中,非託管資源使用之後必須釋放,而using()是使用非託管資源的最佳方式,可以確保資源在程式碼塊結束之後被正確釋放,並且程式碼更簡潔。

這裡說的非託管資源指的是實現IDisposable或IAsyncDisposable介面的類。

using是如何實現資源釋放?本文將予以解答。

 

02.C#中,using的兩個作用 

第一種:引入名稱空間

用法如下:

using System.Text;
using s = System.Text; //為名稱空間定義別名
using static System.Math; //引入型別靜態成員
global using System.Math; //全域性引入

 

第二種:宣告一個物件,並確保該物件在程式碼塊執行完之後被釋放(Dispose())。

這裡主要對第二種用法進行分析。

 

03.using如何實現資源釋放 

通常,我們以下面的形式宣告一個非託管資源,當程式碼塊執行完之後,資源會自動釋放,那程式是如何做到的呢?
using (var file = File.Open("filePath", FileMode.OpenOrCreate)){    //do something}
說起來也簡單:
using(...)語句經編譯器編譯之後,轉換了try{...}finally{...}
上面的程式碼,經程式編譯後的程式碼如下:
FileStream file = File.Open("filePath", FileMode.OpenOrCreate);try{  //do something}finally{  if (file!= null)  {    ((IDisposable)file).Dispose();  }}

兩段程式碼的執行結果是一樣的,對比之下,很明顯,使用using()的程式碼更簡潔。

 

04.實踐探索

實踐出真知,我們通過一個例子,使用反編譯工具(ILSpy或ILDasm)檢視生成的DLL,進行驗證。

首先,定義一個實現了IDisposable介面的類。當然也可以使用.NET中內建的類,這裡採用自定義類是為了驗證,只要是實現了IDisposable介面的類,都可以使用這種方式。

然後,使用using建立資源物件。

最後,檢視編譯後生成的IL程式碼檔案,可以看到確實如上面所說,using(...)語句經編譯器編譯之後,轉換了try{...}finally{...},並且在finally{}中完成了對Dispose()方法的呼叫。 

至此,using()如何完成對非託管資源的釋放,就很清楚了。

 

05.總結 

using()語句編譯後生成 try{...} finally{...} 語句,進而確保資源釋放。

using()是程式中使用非託管資源的最佳方式。

using()的本質是C#中的語法糖。

糖讓人快樂,同樣語法糖也能讓程式設計變得快樂,類似using()的語法糖,可以簡化程式碼,確保必要邏輯的正確執行;糖只是調味劑,同樣語法糖也只是簡化編碼,核心業務邏輯,還需要開發人員完成。

using的用法很簡單,在合適的場景下正確使用,可以讓開發工作事半功倍。

 


認為內容有價值的可以點贊,轉發,關注【公眾號:劉先生的IT樂園】