利用using和try-finally來釋放資源

我以前寫過一篇文章,關於.Net資源釋放問題,也就是對於非內存的資源,最好使用IDisposable接口提供的Dispose來釋放, 
很明顯,Dispose方法是一個外部方法,系統並不會幫你調用。爲了儘早釋放對象所佔用的資源,所以需要保證Dispose方法能儘早被執行。那麼在.Net中提供了一個比較簡便的方法,就是對於實現了IDisposable接口的類型對象提供了using語句。
 
就操作一個數據庫這個例子來說,使用using語句可以如下:
    using( SqlConnection sqlConn = new SqlConnection( yourConnectionString ) )
    {
        sqlConn.Open();//Open connection
   
        //Operate DB here using "sqlConn"  
 
        sqlConn.Close();//Close connection
    }
 
但是有時候當多個對象需要釋放的候,例如:
    SqlConnection sqlConn = new SqlConnection( yourConnectionString );
    SqlCommand sqlComm = new SqlCommand( yourQueryString, sqlConn );
    using(sqlConn as IDisposable)
    using(sqlComm as IDisposable)
    {
        sqlConn.Open();//Open connection
   
        sqlComm.ExecuteNonQuery();//Operate DB here
    }
 
這時候要特別注意,需要確保在發生異常的情況下,所有對象都能正常釋放。顯然,這段程序塊,當構造“sqlComm”對象發生異常,會造成“sqlConn”對象無法及時被釋放。雖說構造函數內部很少發生異常,或者說編寫程序的時候要儘量避免從構造函數內向外散發異常。不過這裏所說的意思是,要儘量把需要釋放的對象放到using或者try-catch程序塊,並作局部的異常處理,避免異常造成有些對象沒有被釋放。那麼改進的方法,例如可以如下。
    using( SqlConnection sqlConn = new SqlConnection( yourConnectionString ) )
    using( SqlCommand sqlComm = new SqlCommand( yourQueryString, sqlConn ) )
    {
        try
        {
            sqlConn.Open();//Open connection
            sqlComm.ExecuteNonQuery();//Operate DB here
        }
        catch( SqlException err )
        {
            MessageBox.Show( err.Message );
        }
        catch( Exception err )
        {
            MessageBox.Show( err.Message );
        }
    }
 但是對於using程序塊來說,它有兩個限制。
第一個就是using所對應的對象必須繼承IDisposable,如果此對象沒有繼承IDisposable接口的話,系統會提示編譯錯誤。
例如:
    using( string strMsg = "My Test" )
        Debug.WriteLine( strMsg );//Can't be compiled
 
第二個using對象檢查是靜態類型檢查,並不支持運行時類型檢查,因此如下形式也會出現編譯錯誤。
    SqlConnection sqlConn = new SqlConnection( yourConnectionString );
    object objConn = sqlConn;
    using ( objConn )
    {
        Debug.WriteLine( objConn.ToString() );//Can't be compiled
    }
 
不過對於後者,可以通過“as”來進行類型轉換方式來改進。
    SqlConnection sqlConn = new SqlConnection( yourConnectionString );
    object objConn = sqlConn;
    using ( objConn as IDisposable )
    {
        Debug.WriteLine( objConn.ToString() );
    }
 
對於Dispose函數的調用來說,使用using程序塊來完成只是最常用的方法,除此外,還可以用try-finally來完成,例如:
    SqlConnection sqlConn = new SqlConnection( yourConnectionString );
    try
    {
        sqlConn.Open();
       
        //Operate DB here using "sqlConn"
    }
    finally
    {
        if( sqlConn != null )
            sqlConn.Dispose();
    }
 
爲了及早釋放對象所佔用的非託管資源,因此要保證Dispose方法能在使用完對象後被調用,.Net提供了using程序塊和try-finally程序塊兩個方法,兩者並沒有太大的區別,可能使用using能使程序看得比較簡明,但是爲了防止異常,需要在using中加入try-catch,這樣反而不如try-finally看得舒服,不過這也只是我個人的看法。總的來說,只要把方法合理整合到應用程序當中纔是最重要的。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章