2008-09-22 80 views
5

在Visual Studio中,當I型行 「Implements IDisposable」,則IDE自動添加:VB.NET - 實現IDisposable時應該添加Finalize方法嗎?

  • 一個disposedValue成員變量
  • 一個Sub Dispose() Implements IDisposable.Dispose
  • 一個Sub Dispose(ByVal disposing As Boolean)

Dispose()應單獨留下,清理代碼應放入Dispose(disposing)

Dispose Finalize Pattern說你也應該覆蓋Sub Finalize()來致電Dispose(False)。爲什麼IDE不添加這個?我必須自己添加它,還是以某種方式隱式地調用?

編輯:任何想法爲什麼IDE會自動添加80%的所需材料,但遺漏了Finalize方法?是不是這種功能全點幫你 不是忘記這些東西?

編輯2:謝謝大家的出色答案,這現在非常有意義!

回答

11

如果您實際上持有的非管理資源不會由垃圾收集器自動清理並將其清理到Dispose()中,那麼是的,您應該在Finalize()中執行相同的操作。

如果您出於某種其他原因實施IDisposable,則不需要實現Finalize()。

最基本的問題是:如果Dispose()沒有被調用並且收集了對象垃圾,會不會泄漏內存?如果是,請執行Finalize。如果不是,你不需要。此外,避免執行Finalize「只是因爲它更安全」。具有自定義終結器的對象可能需要兩次GC傳遞才能釋放它們 - 一次是將它們放到未決的終結器隊列中,另一次是實際釋放它們的內存。

+1

實施處置並不意味着你應該實現一個終結器。您可以在Dispose方法中釋放非託管資源,而不需要終結器。如果你必須實現一個終結器,那麼你的實際清理邏輯應該在一個獨立的函數中,這個函數既可以處理也可以最終確定調用。 – 2008-10-17 08:55:50

+1

這是不正確的。如果您完全依賴Dispose()來釋放非託管資源,則在未調用Dispose的情況下內存將泄漏。這正是終結者的存在。 – Laurent 2009-07-31 09:45:14

+1

不知道爲什麼我之前沒有注意到Scott的評論 - 一定沒有注意到它,但是Laurent是對的 - 如果您的Dispose正在清理非託管資源,則需要進行Finalize以確保安全。不要因爲懶惰而放棄它。 – 2009-07-31 12:07:10

3

不,您不需要進行Finalize,除非您有非託管資源進行清理。

在大多數情況下,類是一次性的原因是因爲它保持對其他託管IDisposable對象的引用。在這種情況下,不需要Finalize方法。

+0

您可以在Dispose方法中釋放非託管資源,而不需要終結器。 – 2008-10-17 08:56:21

1

正如其他人所說,除非直接持有非託管資源,否則不需要實現終結器。此外,假設您使用的是.NET 2.0或更高版本,則不太可能需要實現終結器,因爲通常可以使用SafeHandle來封裝非託管資源。

我寫了一個fairly long blog post,介紹了IDisposable和finalizers的背景和實現,這可能值得一讀,如果你不完全清楚它。

2
Implements IDisposable 

Public Overloads Sub Dispose() Implements IDisposable.Dispose 

    Dispose(True) 
    GC.SuppressFinalize(Me) 

End Sub 

Protected Overloads Sub Dispose(ByVal disposing As Boolean) 

    If disposing Then 
     ' Free other state (managed objects). 
    End If 
    ' Free your own state (unmanaged objects). 
    ' Set large fields to null. 
End Sub 

Protected Overrides Sub Finalize() 

    Dispose(False) 
    MyBase.Finalize() 

End Sub 
相關問題