日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
EffectiveC#原則:調(diào)用Dispose()方法

學習C#時,經(jīng)常會遇到Effective C#原則問題,這里將介紹調(diào)用Dispose()方法解決Effective C#原則問題。

創(chuàng)新互聯(lián)是少有的網(wǎng)站建設(shè)、做網(wǎng)站、營銷型企業(yè)網(wǎng)站、小程序定制開發(fā)、手機APP,開發(fā)、制作、設(shè)計、賣友情鏈接、推廣優(yōu)化一站式服務(wù)網(wǎng)絡(luò)公司,2013年至今,堅持透明化,價格低,無套路經(jīng)營理念。讓網(wǎng)頁驚喜每一位訪客多年來深受用戶好評

Effective C#原則(一)

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

所有包含非托管資源的類型應(yīng)該實現(xiàn)IDisposable接口,另外,當你忘記恰當?shù)奶幚磉@些類型時,它們會被動的創(chuàng)建析構(gòu)函數(shù)。如果你忘記處理這些對象,那些非內(nèi)存資源會在晚些時候,析構(gòu)函數(shù)被確切調(diào)用時得到釋放。這就使得這些對象在內(nèi)存時待的時間更長,從而會使你的應(yīng)用程序會因系統(tǒng)資源占用太多而速度下降。

幸運的是,C#語言的設(shè)計者精確的釋放資源是一個常見的任務(wù)。他們添加了一個關(guān)鍵字來使這變得簡單了。

假設(shè)你寫了下面的代碼:

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

這個例子中的兩個可處理對象沒有被恰當?shù)尼尫牛篠qlConnection和SqlCommand。兩個對象同時保存在內(nèi)存里直到析構(gòu)函數(shù)被調(diào)用。(這兩個類都是從System.ComponentModel.Component繼承來的。)

解決這個問題的方法就是在使用完命令和鏈接后就調(diào)用它們的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.   myConnection.Open();
  7.   mySqlCommand.ExecuteNonQuery();
  8.   mySqlCommand.Dispose( );
  9.   myConnection.Dispose( );
  10. }

Effective C#原則(二)

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

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

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

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

(譯注:就我個人對try/catch/finally塊的使用經(jīng)驗而言,我覺得上面這樣的做法非常不方便。可以保證資源得到釋放,卻無法發(fā)現(xiàn)錯誤。關(guān)于如何同時拋出異常又釋放資源的方法可以參考一下其它相關(guān)資源,如Jeffrey的.Net框架程序設(shè)計,修訂版)

如果你把一個不能處理類型的變量放置在using語句內(nèi),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實現(xiàn)了IDispose接口,那么using語句就會生成資源清理代碼,如果不是,using就退化成使用using(null),這是安全的,但沒有任何作用。如果你對一個對象是否應(yīng)該放在using語句中不是很確定,寧可為了更安全:假設(shè)要這樣做,而且按前面的方法把它放到using語句中。

Effective C#原則(三)

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

 
 
 
  1. public void ExecuteCommand( string connString,  string commandString )
  2. {
  3.   SqlConnection myConnection = null;
  4.   SqlCommand mySqlCommand = null;
  5.   try
  6.   {
  7.     myConnection = new SqlConnection( connString );
  8.     try
  9.     {
  10.       mySqlCommand = new SqlCommand( commandString,
  11.       myConnection );
  12.       myConnection.Open();
  13.       mySqlCommand.ExecuteNonQuery();
  14.     }
  15.     finally
  16.     {
  17.       if ( mySqlCommand != null )
  18.         mySqlCommand.Dispose( );
  19.     }
  20.   }
  21.   finally
  22.   {
  23.     if ( myConnection != null )
  24.       myConnection.Dispose( );
  25.   }
  26. }

每一個using語句生成了一個新的嵌套的try/finally塊。我發(fā)現(xiàn)這是很糟糕的結(jié)構(gòu),所以,如果是遇到多個實現(xiàn)了IDisposable接口的對象時,我更愿意寫自己的try/finally塊:

 
 
 
  1. public void ExecuteCommand( string connString,  string commandString )
  2. {
  3.   SqlConnection myConnection = null;
  4.   SqlCommand mySqlCommand = null;
  5.   try {
  6.     myConnection = new SqlConnection( connString );
  7.     mySqlCommand = new SqlCommand( commandString,
  8.       myConnection );
  9.     myConnection.Open();
  10.     mySqlCommand.ExecuteNonQuery();
  11.   }
  12.   finally
  13.   {
  14.     if ( mySqlCommand != null )
  15.       mySqlCommand.Dispose();
  16.     if ( myConnection != null )
  17.       myConnection.Dispose();
  18.   }
  19. }

(譯注:作者里的判斷對象是否為null是很重要的,特別是一些封裝了COM的對象,有些時候的釋放是隱式的,當你再釋放一些空對象時會出現(xiàn)異常。例如:同一個COM被兩個不同接口的變量引用時,在其中一個上調(diào)用了Dispose后,另一個的調(diào)用就會失敗。在.Net里也要注意這樣的問題,所以要判斷對象是否為null)

然而,請不要自作聰明試圖用as來寫這樣的using語句:

 
 
 
  1. public void ExecuteCommand( string connString,  string commandString )
  2. {
  3.   // Bad idea. Potential resource leak lurks!
  4.   SqlConnection myConnection =    new SqlConnection( connString );
  5.   SqlCommand mySqlCommand = new SqlCommand( commandString, myConnection );
  6.       using ( myConnection as IDisposable )
  7.       using (mySqlCommand as IDisposable )
  8.       {
  9.         myConnection.Open();
  10.         mySqlCommand.ExecuteNonQuery();
  11.       }
  12. }

這看上去很清爽,但有一個狡猾的(subtle )的bug。 如果SqlCommand()的構(gòu)造函數(shù)拋出異常,那么SqlConnection對象就不可能被處理了。你必須確保每一個實現(xiàn)了IDispose接口的對象分配在在using范圍內(nèi),或者在try/finally塊內(nèi)。否則會出現(xiàn)資源泄漏。

目前為止,你已經(jīng)學會了兩種最常見的情況。無論何時在一個方法內(nèi)處理一個對象時,使用using語句是最好的方法來確保申請的資源在各種情況下都得到釋放。當你在一個方法里分配了多個(實現(xiàn)了IDisposable接口的)對象時,創(chuàng)建多個using塊或者使用你自己的try/finally塊。

對可處理對象的理解有一點點細微的區(qū)別。有一些對象同時支持Disponse和Close兩個方法來釋放資源。SqlConnection就是其中之一,你可以像這樣關(guān)閉SqlConnection:

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

這個版本關(guān)閉了鏈接,但它確實與處理對象是不一樣的。Dispose方法會釋放更多的資源,它還會告訴GC,這個對象已經(jīng)不再須要析構(gòu)了(譯注:關(guān)于C#里的析構(gòu),可以參考其它方面的書籍)。調(diào)用Dispose()方法的GC.SuppressFinalize(),但Close()一般不會。結(jié)果就是,對象會到析構(gòu)隊列中排隊,即使析構(gòu)并不是須要的。當你有選擇時,Dispose()比Colse()要好。你會在原則18里學習更更精彩的內(nèi)容。

Dispose()并不會從內(nèi)存里把對象移走,對于讓對象釋放非托管資源來說是一個hook。這就是說你可能遇到這樣的難題,就是釋放一個還在使用的對象。不要釋放一個在程序其它地方還在引用的對象。

在某些情況下,C#里的資源管理比C++還要困難。你不能指望確定的析構(gòu)函數(shù)來清理你所使用的所有資源。但垃圾回收器卻讓你更輕松,你的大從數(shù)類型不必實現(xiàn)IDisposable接口。在.Net框架里的1500多個類中,只有不到100個類實現(xiàn)了IDisposable接口。當你使用一個實現(xiàn)了IDisposeable接口的對象時,記得在所有的類里都要處理它們。你應(yīng)該把它們包含在using語句中,或者try/finally塊中。不管用哪一種,請確保每時每刻對象都得到了正確的釋放。


新聞名稱:EffectiveC#原則:調(diào)用Dispose()方法
文章位置:http://www.5511xx.com/article/dhediij.html