Effective C#:利用using和try/finally語句來清理資源
在記憶體資源分配方面,.NET可以分為託管資源和非託管資源兩部分。對於託管資源,.NET框架會負責進行垃圾回收的工作;對於非託管的資源,我們需要手動去釋放資源。通常情況下,我們使用IDisposable介面中的Dispose()方法釋放資源,而呼叫Dispose()方法的責任,由資源的擁有者或者物件的擁有者執行,即我們這些程式設計師,確保呼叫Dispose()方法的最佳方式就是使用using或者try/finally語句塊。
所有擁有非託管資源的型別,都應該實現IDisposable介面,另外作為一種保障措施,這種型別還會建立一個終結器,以防止我們忘記呼叫 Dispose()方法,如果我們忘記了呼叫Dispose()方法,那麼其中的非記憶體資源會在隨後終結器執行時被釋放。這樣物件在記憶體中存留的時間會比較長,應用程式對資源的清理也比較慢。
我們可以使用using的方式來強制呼叫Dispose()方法,檢視以下程式碼。
程式碼
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 }
上述程式碼中,SqlConnection和SqlCommand是兩個需要釋放資源的地方,其中在變數宣告時,使用了using,它的作用和以下的程式碼相同。
程式碼
1 SqlConnection myConnection = null;
2
3 // Example Using clause:
4 using ( myConnection = new SqlConnection( connString ))
5 {
6 myConnection.Open();
7 }
8
9 // example Try / Catch block:
10 try {
11 myConnection = new SqlConnection( connString );
12 myConnection.Open();
13 }
14 finally {
15 myConnection.Dispose( );
16 }
注意,如果我們對一個沒有實現IDisposable介面的物件使用using語句,那麼C#編譯器會產生錯誤,只有當編譯時型別實現了IDisposable介面時,using語句才會正常編譯。
我們可以使用as進行型別轉換,以防止出現編譯錯誤。
1 object bj = Factory.CreateResource( );
2 using ( obj as IDisposable )
3 Console.WriteLine( obj.ToString( ));
上述程式碼中,如果obj沒有實現IDisposable介面,那麼變為using(null),這種做法很安全,不會產生變異錯誤,只是不會做任何事情。
在釋放某些物件的資源時,我們會發現有些型別既支援Dispose()方法,也支援Close()方法,例如SqlConnection型別,我們也可以通過呼叫Close()方法來釋放資源。
Dispose()方法和Close()方法的區別:Dispose()方法除了釋放資源之外,還會通知垃圾收集器對該物件不再需要執行終結操作,它是通過呼叫GC.SuppressFinalize()方法來實現的;Close()方法一般不會這麼處理,因此在呼叫了Close()方法的物件,依然會停留在終結佇列中。因此,我們應該優先呼叫Dispose()方法。
Dispose()方法不會將物件從記憶體上刪除,它只是讓物件釋放非託管資源,這意味著如果釋放的是仍被使用的物件,那麼可能會遇到一些問題,因此,我們不應該釋放那些仍然被程式其他地方引用的物件。
作者:李勝攀
出處:http://wing011203.cnblogs.com/
所有擁有非託管資源的型別,都應該實現IDisposable介面,另外作為一種保障措施,這種型別還會建立一個終結器,以防止我們忘記呼叫 Dispose()方法,如果我們忘記了呼叫Dispose()方法,那麼其中的非記憶體資源會在隨後終結器執行時被釋放。這樣物件在記憶體中存留的時間會比較長,應用程式對資源的清理也比較慢。
我們可以使用using的方式來強制呼叫Dispose()方法,檢視以下程式碼。
程式碼
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 }
上述程式碼中,SqlConnection和SqlCommand是兩個需要釋放資源的地方,其中在變數宣告時,使用了using,它的作用和以下的程式碼相同。
程式碼
1 SqlConnection myConnection = null;
2
3 // Example Using clause:
4 using ( myConnection = new SqlConnection( connString ))
5 {
6 myConnection.Open();
7 }
8
9 // example Try / Catch block:
10 try {
11 myConnection = new SqlConnection( connString );
12 myConnection.Open();
13 }
14 finally {
15 myConnection.Dispose( );
16 }
注意,如果我們對一個沒有實現IDisposable介面的物件使用using語句,那麼C#編譯器會產生錯誤,只有當編譯時型別實現了IDisposable介面時,using語句才會正常編譯。
我們可以使用as進行型別轉換,以防止出現編譯錯誤。
1 object bj = Factory.CreateResource( );
2 using ( obj as IDisposable )
3 Console.WriteLine( obj.ToString( ));
上述程式碼中,如果obj沒有實現IDisposable介面,那麼變為using(null),這種做法很安全,不會產生變異錯誤,只是不會做任何事情。
在釋放某些物件的資源時,我們會發現有些型別既支援Dispose()方法,也支援Close()方法,例如SqlConnection型別,我們也可以通過呼叫Close()方法來釋放資源。
Dispose()方法和Close()方法的區別:Dispose()方法除了釋放資源之外,還會通知垃圾收集器對該物件不再需要執行終結操作,它是通過呼叫GC.SuppressFinalize()方法來實現的;Close()方法一般不會這麼處理,因此在呼叫了Close()方法的物件,依然會停留在終結佇列中。因此,我們應該優先呼叫Dispose()方法。
Dispose()方法不會將物件從記憶體上刪除,它只是讓物件釋放非託管資源,這意味著如果釋放的是仍被使用的物件,那麼可能會遇到一些問題,因此,我們不應該釋放那些仍然被程式其他地方引用的物件。
作者:李勝攀
出處:http://wing011203.cnblogs.com/
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-625132/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JavaScript try catch finally 語句JavaScript
- JavaScript try/catch/finally 語句JavaScript
- Java的finally語句Java
- c# 異常處理try catch finally_throwC#
- Java try catch finallyJava
- Java語法糖: 使用 try-with-resources 語句安全地釋放資源Java
- C#快速入門教程(23)—— using語句和IDisposable介面C#
- c#之異常處理tcbs_try_catch_finallyC#
- Java趣味分享:try/finallyJava
- Java try catch finally 總結Java
- python怎麼寫try語句Python
- try throw catch 語句檢測input值
- python中try..except語句如何使用?Python
- python中try語句的工作過程Python
- 《Effective C#》C#
- [Java基礎]try-catch-finally 和 return 的執行順序Java
- finally語句塊的有限範圍(skycto JEEditor)
- 關於 Java 中 finally 語句塊的深度辨析Java
- java中異常處理finally和return語句的執行順序Java
- try{}裡有一個return語句,那麼緊跟在這個try後的finally{}裡的code會不會被執行,什麼時候被執行?
- Effective MySQL之SQL語句最佳化 小結MySql
- Oracle高資源消耗SQL語句定位OracleSQL
- Effective Java -- 使用try-with-resources優化程式碼Java優化
- Will it finally: 關於 try/catch 的一些細節
- python 中 try...finally... 的優雅實現Python
- 【轉】java中異常與try catch finally詳解Java
- Java中的try、catch、finally塊簡單的解析Java
- C++及Windows異常處理(try,catch; __try,__finally; __try, __except)——一道筆試題引起的探究C++Windows筆試
- 1.4 資料庫和常用SQL語句(正文)——MySQL資料庫命令和SQL語句資料庫MySql
- 【搞定面試官】try中有return,finally還會執行嗎?面試
- try-catch-finally,被你忽略掉的執行順序
- Java含有return 的try catch finally的執行順序Java
- C++異常處理:try,catch,throw,finally的用法C++
- C# 託管資源和非託管資源C#
- finally語句在return執行之後,return返回之前執行
- java try(){}catch(){}自動資源釋放Java
- 使用 TRY/CATCH 語句解決 SQL Server 2005 死鎖SQLServer
- 利用SQL語句完成位操作 (轉)SQL