Effective C#:利用using和try/finally語句來清理資源

iDotNetSpace發表於2010-01-14
    在記憶體資源分配方面,.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/

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-625132/,如需轉載,請註明出處,否則將追究法律責任。

相關文章