簡體   English   中英

我應該在哪些類中使用C#的using語句?

[英]What classes should I use C#'s using statement with?

我已閱讀並且相信我理解C#的using語句的作用(如果我錯了,請糾正我):將IDisposable對象初始化為對有限范圍( using塊)只讀。 我知道您可以在using之前using初始化,並且不限制范圍,但是建議您在此處使用:

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

我並不總是注意什么類是什么的子類。 我不太確定哪些類從IDisposable繼承。 我不僅好奇在using語句中可以使用哪些類,而且我的同事希望在using塊中找到哪些類? using塊中應該包含哪些類? 另外,不使用using塊而不調用Dispose真的有什么問題嗎? 它只是關於內存還是穩定性?

嚴格來說,任何實現IDisposable且范圍僅限於該功能的對象都應位於using塊內。 存在IDisposable接口,以允許處理非托管資源(數據庫連接,文件句柄,窗口句柄等)的類以及時,確定的方式處置這些資源。

通常,在類中使用IDisposable對象的三種方式:

  1. 在單個方法調用的范圍內,既創建對象又不再需要該對象。 這是很常見的,並且在using可以(並且應該)使用。
  2. 對象由類創建(或傳遞給類),並且對象的生存期超出單個方法調用的范圍,但不超過類的生存期。 例如,您的類創建一個Stream並且需要在對象的生命周期內使用它。 在這種情況下,您的類應自己實現IDisposable並在調用自己的Dispose方法時Dispose您擁有的對象。 例如System.IO.StreamWriter
  3. 該對象將傳遞給該類,但是該類並不“擁有”它。 這意味着IDisposable對象的可用生存期超出了單個方法調用的范圍,並且可能超出了對象的生存期。 在這種情況下,必須由其他人負責致電Dispose

第一種情況是您會遇到的最常見情況,這就是為什么using塊存在的原因。 即使在出現異常的情況下,也要確保確保將對象丟棄。

一些例子:

  • 流類
  • 數據庫連接/命令
  • 控制項

沒有實現IDisposable的類的詳盡列表,因為該列表將很大,並且充滿了您可能永遠不會遇到的類。 想想類什么; 它會打開某種需要關閉的連接或文件嗎? 通常, 它獲取某種需要釋放的資源嗎? 如果是這樣,它可能會實現它。 在一個基本水平,如果編譯器允許您括在using ,那么它實現IDisposable

至於調用Dispose的后果,請不要考慮。 呼叫Dispose 誠然,防御性標准是,如果您的類直接使用非托管資源,那么您應該定義一個終結器,該終結器將在對象被收集且有人調用失敗的情況下調用dispose,但這不是設計選擇。 就我所知。

這與內存無關。 它與其他資源有關,例如文件句柄,數據庫連接等。

基本上,如果一個類實現了IDisposable ,則表明您應該在完成后將其處置,因為它可能具有不受管的資源,而留下的資源卻很昂貴。 (例如,連接池可能用盡了連接,或者文件句柄將保持打開狀態,從而防止另一段代碼再次打開同一文件)。

您應該始終在實現IDisposable任何類上調用Dispose ,這最容易通過using塊完成。

這不僅與記憶有關。 這也不只是資源。 這是關於正確性。

StreamWriter是一個著名的例子。 微軟甚至開發了MDA來捕獲某些程序員忘記調用Dispose 這不僅僅是內存或資源:在StreamWriter示例中,正在寫入的文件可能會被截斷。

我不得不一次追蹤一個討厭的錯誤(實際上是在老板的代碼中),在該錯誤中數據庫事務被回滾...原來原因是沒有調用Dispose ,所以它試圖提交進程退出時,磁盤空間太大(在退出過程中終結器超時)。 修復只是一些using塊。

第三個示例:Microsoft的Managed ESENT包裝器類具有“三層”處置方案,該方案要求以正確的順序調用Dispose (最后是“外部”類)。

因此,在三個真實的示例中,如果未正確調用Dispose將導致不正確的行為 其他類可能會表現出類似的行為。

通常,您應該始終調用Dispose

至少,所有使用非托管資源的類

不使用using塊而不調用Dispose絕對有很多錯誤,您很可能會泄漏內存和/或資源。 使用是一種方便,但是您實際上應該在類從IDisposable派生的任何對象中調用Dispose。

至於什么課是一次性的,您可以自己進行智能感知,或者只是從經驗中學習。 一些常見的功能包括Image及其子級,實際上是System.Drawing命名空間的大部分,大量文件流,數據庫連接等。

至於何時應調用-盡快。 如果您知道它是一次性的,並且知道您已經用完了,請致電Dispose。

我相信許多實現IDisposable的.NET基類都實現了一次性模式,這意味着當垃圾收集器來獲取它們時,它們將被正確處理。 但是即使如此,您仍然應該在完成工作后處理事情,因為

  1. 您可能會留下一個參考文獻(泄漏),並且它不會被處置,或者
  2. GC可能暫時不會出現。

此外,對於您自己編寫的類,垃圾回收並不等同於對非托管資源的正確處理-這是常見的混淆。 一次性模式需要自己實現。

類實現IDisposable主要原因是釋放非托管資源。 垃圾回收器將在托管資源超出范圍時釋放托管資源,它認為合適,但不了解非托管資源。 調用Dispose方法將顯式釋放資源。

如果您不使用using塊或調用Dispose方法,則將出現內存泄漏問題,這又可能導致穩定性問題。

在處理實現IDisposable類時,應始終使用using塊。 盡管您可能更喜歡Try.. Catch.. Finally確保在finally塊中調用Dispose ,以便您可以處理異常。

IDisposable的目的是使與非托管資源(例如文件,數據庫或圖形上下文)進行交互的對象能夠自行清理。 using語句是以下構造的方便快捷方式

var disposable = new MemoryStream();
try
{
  //do some work with the disposable object
}
finally
{
  if (disposable!=null)
     disposable.Dispose();  
}

當然,問題是要知道哪些對象實現了IDisposable ...不幸的是,除了文檔之外,沒有自動的方法來知道。 盡管我相信有一個Fxcop設置可以檢查在使用之外使用的IDisposables。

您不必擔心在using塊下使用哪些類。 如果您在using語句下使用過的代碼未實現IDisposbale,則它將向您顯示紅色/藍色波浪。 這樣您就可以知道它缺少idisposable接口。 據我所使用的幾乎所有框架類,都已實現Idisposable。 但是在自定義類中,您需要實現

要使用using進行調用的類的准備者是:

  • 數據庫連接,命令和數據讀取器
  • 讀者和作家

您還應該處置更多的類,但是上面的那些類經常被使用,通常在狹窄的使用范圍內。

是的-不使用using和不調用dispose存在問題。 經典的Web應用程序不會關閉其與數據庫的連接,而是在連接保持打開狀態時有效地從數據庫服務器吸收資源。

暫無
暫無

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

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