2008-09-22 11 views
5

In Visual Studio, wenn ich die Zeile "Implements IDisposable" eingeben, fügt die IDE automatisch:VB.NET - Sollte eine Finalize-Methode hinzugefügt werden, wenn IDisposable implementiert wird?

  • ein disposedValue Membervariable
  • ein Sub Dispose() Implements IDisposable.Dispose
  • ein Sub Dispose(ByVal disposing As Boolean)

Die Dispose() sein sollte allein gelassen, und der Bereinigungscode sollte in Dispose(disposing) gelegt werden.

Die Dispose Finalize Pattern besagt jedoch, dass Sie auch Sub Finalize() überschreiben sollten, um Dispose(False) zu rufen. Warum fügt die IDE das nicht hinzu? Muss ich es selbst hinzufügen oder wird es irgendwie implizit genannt?

EDIT: Eine Idee, warum die IDE automatisch 80% der erforderlichen Sachen hinzufügt, aber die Finalize-Methode auslässt? Ist nicht der ganze Sinn dieser Art von Feature, um Ihnen zu helfen nicht diese Dinge vergessen?

EDIT2: Vielen Dank für Ihre ausgezeichnete Antworten, das macht jetzt Sinn!

Antwort

11

Wenn Sie tatsächlich nicht verwaltete Ressourcen halten, die nicht automatisch vom Garbage Collector bereinigt und in Dispose() bereinigt werden, dann sollten Sie das Gleiche in Finalize() tun.

Wenn Sie IDisposable aus einem anderen Grund implementieren, ist die Implementierung von Finalize() nicht erforderlich.

Die grundlegende Frage ist dies: Wenn Dispose() nicht aufgerufen wurde und Ihr Objekt Müll gesammelt wurde, würde Speicherleck? Wenn ja, implementieren Sie Finalisieren. Wenn nicht, müssen Sie nicht. Vermeiden Sie auch, Finalize "nur weil es sicherer ist" zu implementieren. Objekte mit benutzerdefinierten Finalizern können möglicherweise zwei GC-Durchgänge benötigen, um sie zu befreien - einmal, um sie in die Warteschlange der ausstehenden Finalizer zu setzen, und einen zweiten Durchlauf, um ihren Speicher freizugeben.

+1

Die Implementierung von Dispose bedeutet nicht, dass Sie auch einen Finalizer implementieren sollten. Sie können nicht verwaltete Ressourcen in einer Dispose-Methode freigeben, ohne jemals einen Finalizer zu benötigen. Wenn Sie einen Finalizer implementieren müssen, sollte sich Ihre tatsächliche Bereinigungslogik in einer separaten Funktion befinden, die den Aufruf sowohl verwerfen als auch abschließen kann. –

+1

Das ist falsch.Wenn Sie sich ausschließlich auf Dispose() verlassen, um nicht verwaltete Ressourcen freizugeben, wird Speicher ausgelaufen, wenn Dispose nicht aufgerufen wird. Genau dafür ist der Finalizer da. – Laurent

+1

Ich bin mir nicht sicher, warum ich nicht schon vor Scotts Kommentar residiert habe - ich hätte es nicht bemerkt, aber Laurent hat Recht - wenn Ihr Dispose unmanaged Ressourcen aufräumt, ist ein Finalize zur Sicherheit erforderlich. Lass es nicht aus, weil du faul bist. –

3

Nein, Sie brauchen Finalize nur, wenn Sie nicht verwaltete Ressourcen zum Bereinigen haben.

In den meisten Fällen liegt der Grund dafür, dass eine Klasse entsorgbar ist, weil sie Verweise auf andere verwaltete IDisposable-Objekte enthält. In diesem Fall ist keine Finalize-Methode notwendig oder wünschenswert.

+0

Sie können nicht verwaltete Ressourcen in einer Dispose-Methode freigeben, ohne dass Sie jemals einen Finalizer benötigen. –

+0

Sie können, aber wenn Dispose nicht aufgerufen wird, dann werden Sie wahrscheinlich Speicher ohne eine Finalize-Methode auch verlieren. –

1

Wie andere bereits gesagt haben, müssen Sie keinen Finalizer implementieren, es sei denn, Sie verwalten direkt nicht verwaltete Ressourcen. Angenommen, Sie arbeiten in .NET 2.0 oder höher, ist es unwahrscheinlich, dass Sie jemals einen Finalizer implementieren müssen, da SafeHandle normalerweise dazu verwendet werden kann, Ihre nicht verwalteten Ressourcen zu umbrechen.

Ich schrieb eine fairly long blog post über den Hintergrund und die Implementierung von IDisposable und Finalizer eine Weile zurück, die eine Lesung wert sein kann, wenn Sie nicht ganz klar darüber sind.

+0

Sie können nicht verwaltete Ressourcen in einer Dispose-Methode freigeben, ohne jemals einen Finalizer zu benötigen. –

+0

Nun ja, das ist der Sinn des IDisposable-Musters. Wenn jedoch vergessen wird, Dispose anzurufen, ist der Finalizer ein Schutz, der sie schließlich aufräumt, was nicht vergessen werden kann, weil er von der Laufzeit aufgerufen wird. –

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 
+3

Eine einzelne Code-Ebene ist nicht sehr nützlich. Versuchen Sie, konstruktiver zu sein, mit einer kleinen Beschreibung und Argumentation hinter dem bereitgestellten Code. –

Verwandte Themen