簡體   English   中英

非托管資源,IDisposable和自定義類型

[英]Unmanaged Resources, IDisposable and Custom Types

關於這個主題的另一個主題,因為我厭倦了閱讀無數的主題,以找到我的問題的答案:)

可以說我們有以下課程:

public class MyClass
{
   private const string conString = "connection string";

   private int Operation()
   {
      int count = 0;

      using(var con = SqlConnection(conString))
      {
         string select_cmd = "SELECT * FROM TABLE";

         using(var cmd = new SqlCommand(select_cmd, con))
         {
            using(var reader = cmd.ExecuteReader())
            {
               while(reader != null && reader.Read())
                  count++;
            }
         }
      }

      return count;
   }

}

由於在using語句中實例化了與數據庫的連接,因此將調用con.close()和最終的con.dispose()方法,是否需要為MyClass實現IDisposable? 當MyClass超出范圍時,它會被垃圾收集嗎?

編輯:

謝謝你的回復,這就是我的想法,但我需要說清楚。 還有一個問題。

如果我的類有幾個在數據庫上做一些工作的Operations(),從資源消耗的角度來看,有一個更好的做法是擁有一個SqlConnection成員,instanciate並在類構造函數上打開它並實現IDisposable來關閉它而不是在每個操作中使用“using”語句(在每個操作上打開和關閉數據庫)? 當然,我只應該在使用語句中實例化和使用MyClass對象。

不,如果您的類在Operation()方法之外持有SqlConnection實例,那么您只需要實現IDisposable,這樣它就可以與類本身一起保持活動狀態(例如,如果您將它分配給類成員字段或屬性)。

在您的類超出范圍之前,SqlConnection實例將被標記為有資格進行清理,因為該實例超出了使用塊中的范圍。 最重要的是,通過Dispose調用釋放了非托管數據庫連接(由SqlConnection封裝)。 當GC感到有足夠的壓力來證明進行GC傳遞時,將釋放SqlConnection的托管部分。

至於你的類實例,它也將由GC自行決定釋放,除非你在應用程序的整個生命周期中創建和銷毀你的類的大量實例,否則你不必擔心這一點(我認為數以百萬計)。

編輯

對於第二個問題,最好每個方法使用和配置SqlConnection實例,因為這個特定的數據庫客戶端類在內部實現了連接池(即:當你將它處理一段時間時它並沒有真正關閉連接,所以當一個新的時候創建SqlConnection,它從打開的連接池中重用一個)。

請參閱(舊但有效): http//msdn.microsoft.com/en-us/library/8xx3tyca%28v=vs.71%29.aspx

如果您使用的數據庫客戶端API沒有實現自己的池,那么最好按照您的建議手動管理它。 但是,您必須小心同步對連接的訪問​​(即:不要讓2個線程同時使用它)並自己管理生命周期問題(例如:如果您的類在應用程序的所有持續時間內保持活動狀態,那么' ll無限期地打開數據庫資源......等等。)

大多數現代的(MySql Connector.NET,SQL Server)都實現了池化。

Operation()完成之后,將處理該方法中使用的所有非托管資源。 它沒有理由實現IDisposable MyClass不會保持任何非托管資源的打開,因此不需要實現該接口。

關於你的第二個問題,你的類的實例將像任何其他托管對象一樣被垃圾收集。

不,沒有必要實現到IDisposable接口,你沒有資源可以釋放。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM