程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 利用using和try/finally語句來清理資源

利用using和try/finally語句來清理資源

編輯:C#入門知識

    使用非托管資源的類型必須實現IDisposable接口的Dispose()方法來精確的釋放系統資源。.Net環境的這一規則使得釋放資源代碼的職責 是類型的使用者,而不是類型或系統。因此,任何時候你在使用一個有Dispose()方法的類型時,你就有責任來調用Dispose()方法來釋放資源。 最好的方法來保證Dispose()被調用的結構是使用using語句或者try/finally塊。

        所有包含非托管資源的類型應該實現IDisposable接口,另外,當你忘記恰當的處理這些類型時,它們會被動的創建析構函數。如果你忘記處理這些對 象,那些非內存資源會在晚些時候,析構函數被確切調用時得到釋放。這就使得這些對象在內存時待的時間更長,從而會使你的應用程序會因系統資源占用太多而速 度下降。

        幸運的是,C#語言的設計者精確的釋放資源是一個常見的任務。他們添加了一個關鍵字來使這變得簡單了。假設你寫了下面的代碼:

  1. public void ExecuteCommand( string connString,  
  2. string commandString )  
  3. {  
  4. SqlConnection myConnection = new SqlConnection( connString );  
  5. SqlCommand mySqlCommand = new SqlCommand( commandString,  
  6.     myConnection );  
  7.   
  8. myConnection.Open();  
  9. mySqlCommand.ExecuteNonQuery();  
  10. }  

        這個例子中的兩個可處理對象沒有被恰當的釋放:SqlConnection和SqlCommand。兩個對象同時保存在內存裡直到析構函數被調用。(這兩 個類都是從System.ComponentModel.Component繼承來的。)

 

        解決這個問題的方法就是在使用完命令和鏈接後就調用它們的Dispose:

  1. public void ExecuteCommand( string connString,  string commandString )  
  2. {  
  3. SqlConnection myConnection = new SqlConnection( connString );  
  4. SqlCommand mySqlCommand = new SqlCommand( commandString,  
  5.     myConnection );  
  6.   
  7. myConnection.Open();  
  8. mySqlCommand.ExecuteNonQuery();  
  9.   
  10. mySqlCommand.Dispose( );  
  11. myConnection.Dispose( );  
  12. }  

        這很好,除非SQL命令在執行時拋出異常,這時你的Dispose()調用就永遠不會成功。using語句可以確保Dispose()方法被調用。當你把 對象分配到using語句內時,C#的編譯器就把這些對象放到一個try/finally塊內:

  1. public void ExecuteCommand( string connString,  
  2. string commandString )  
  3. {  
  4. using ( SqlConnection myConnection = new  
  5.     SqlConnection( connString ))  
  6. {  
  7.     using ( SqlCommand mySqlCommand = new  
  8.       SqlCommand( commandString,  
  9.       myConnection ))  
  10.     {  
  11.       myConnection.Open();  
  12.       mySqlCommand.ExecuteNonQuery();  
  13.     }  
  14. }  
  15. }  

        當你在一個函數內使用一個可處理對象時,using語句是最簡單的方法來保證這個對象被恰當的處理掉。當這些對象被分配時,會被編譯器放到一個 try/finally塊中。下面的兩段代碼編譯成的IL是一樣的

  1. SqlConnection myConnection = null;  
  2.   
  3. // Example Using clause:  
  4. using ( myConnection = new SqlConnection( connString ))  
  5. {  
  6. myConnection.Open();  
  7. }  
  8.   
  9.   
  10. // example Try / Catch block:  
  11. try {  
  12. myConnection = new SqlConnection( connString );  
  13. myConnection.Open();  
  14. }  
  15. finally {  
  16. myConnection.Dispose( );  
  17. }  

        如果你把一個不能處理類型的變量放置在using語句內,C#編譯器給出一個錯誤,例如:

  1. // Does not compile:  
  2. // String is sealed, and does not support IDisposable.  
  3. using( string msg = "This is a message" )  
  4. Console.WriteLine( msg );  

        using只能在編譯時,那些支持IDispose接口的類型可以使用,並不是任意的對象

  1. // Does not compile.  
  2. // Object does not support IDisposable.  
  3. using ( object obj = Factory.CreateResource( ))  
  4. Console.WriteLine( obj.ToString( ));  

        如果obj實現了IDispose接口,那麼using語句就會生成資源清理代碼,如果不是,using就退化成使用using(null),這是安全 的,但沒有任何作用。如果你對一個對象是否應該放在using語句中不是很確定,寧可為了更安全:假設要這樣做,而且按前面的方法把它放到using語句 中。

        這裡講了一個簡單的情況:無論何時,當你在某個方法內使用一個可處理對象時,把這個對象放在using語句內。現在你學習一些更復雜的應用。還是前面那個 例子裡須要釋放的兩個對象:鏈接和命令。前面的例子告訴你創建了兩個不同的using語句,一個包含一個可處理對象。每個using語句就生成了一個不同 的try/finally塊。等效於你寫了這樣的代碼:

  1. public void ExecuteCommand( string connString,  
  2. string commandString )  
  3. {  
  4. SqlConnection myConnection = null;  
  5. SqlCommand mySqlCommand = null;  
  6. try  
  7. {  
  8.     myConnection = new SqlConnection( connString );  
  9.     try  
  10.     {  
  11.       mySqlCommand = new SqlCommand( commandString,  
  12.     &nbs

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved