3
尚未

作爲我厭倦了閱讀了無數話題找到一個答案,我的問題:)非託管資源,IDisposable接口和自定義類型

主題的另一個話題假設我們有下面的類:

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()和condispose()方法將被調用,是否需要爲MyClass實現IDisposable? MyClass在超出範圍時會被垃圾收集嗎?

編輯:

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

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

+0

查看我的更新回答 – 2012-04-24 15:44:39

回答

3

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

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

至於你的類實例,它也會在GC的判斷中被釋放,這是你不需要關心的東西,除非你在整個生命週期中創建和銷燬大量的類實例你的應用程序(數百萬我想)。

編輯

關於第二個問題,它是更好地使用和每個方法處理SqlConnection的實例,因爲這個特殊的數據庫客戶端類內部實現連接池(即:它並不真正關閉連接,當你處理一段時間,這樣當創建一個新的SqlConnection時,它會重新使用打開的連接池中的一個)。

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

如果您使用數據庫客戶端API沒有實現自己的彙集,它也許不如手動你建議管理此。但是,您必須小心同步對連接的訪問​​(即:不要讓2個線程同時使用它)並自行管理生命週期問題(例如:如果您的課程在應用程序的所有持續時間內保持活動狀態,將持有無限期打開的數據庫資源等)

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

+0

非常感謝您的詳細解答,非常感謝! – Pantelis 2012-04-25 05:48:00

1

Operation()已完成後,將處理該方法中使用的所有非託管資源。沒有理由實施IDisposableMyClass不保留任何非託管資源,因此它不需要實現該接口。

關於你的第二個問題,你的類的實例會像其他被管理對象一樣被垃圾回收。

0

不,不需要實現IDisposable接口,你沒有資源釋放。

相關問題