VB.NET - Sollte eine Abschlussmethode bei der Implementierung iDisposable hinzugefügt werden?
-
02-07-2019 - |
Frage
In Visual Studio, wenn ich die Linie eingeben "Implements IDisposable
", Die IDE fügt automatisch hinzu:
- a
disposedValue
Mitgliedsvariable - a
Sub Dispose() Implements IDisposable.Dispose
- a
Sub Dispose(ByVal disposing As Boolean)
Das Dispose()
sollte in Ruhe gelassen werden, und der Aufräumcode sollte eingefügt werden Dispose(disposing)
.
Jedoch das Abschluss des Musters entsorgen sagt, du solltest auch außer Kraft setzen Sub Finalize()
anrufen Dispose(False)
. Warum fügt die IDE das auch nicht hinzu? Muss ich es selbst hinzufügen oder wird es irgendwie implizit genannt?
BEARBEITEN: Irgendeine Idee, warum die IDE automatisch 80% der erforderlichen Dinge hinzufügt, aber die Abschlussmethode auslässt? Ist nicht der springende Punkt dieser Art von Funktion, die Ihnen hilft nicht diese Dinge vergessen?
Edit2: Vielen Dank für Ihre hervorragenden Antworten. Das macht jetzt vollkommen sinnvoll!
Lösung
Wenn Sie tatsächlich nicht verwaltete Ressourcen halten, die vom Müllsammler nicht automatisch aufgeräumt werden und diese in Ihrem Dispose () aufräumen, sollten Sie dasselbe in Finalize () tun.
Wenn Sie aus einem anderen Grund idisposable implementieren, ist die Implementierung von Finalize () nicht erforderlich.
Die grundlegende Frage lautet: Wenn Dispose () nicht angerufen und Ihr Objektmüll gesammelt wurde, würde das Speicher auslaufen? Wenn ja, implementieren Sie die Abschluss. Wenn nein, müssen Sie nicht. Vermeiden Sie auch die Implementierung der Abschluss "nur weil es sicherer ist". Objekte mit kundenspezifischen Finalizern können möglicherweise zwei GC -Pässe benötigen, um sie zu befreien - einmal, um sie in die anstehende Schlange des Finalizers zu setzen, und einen zweiten Pass, um ihren Speicher tatsächlich zu befreien.
Andere Tipps
Nein, Sie müssen nicht abgeschlossen sein, wenn Sie nicht verwaltete Ressourcen zum Aufräumen haben.
In den meisten Fällen ist der Grund, warum eine Klasse verfügbar ist, weil sie Verweise auf andere verwaltete identifizierbare Objekte hält. In diesem Fall ist keine Abschlussmethode erforderlich oder wünschenswert.
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
Wie andere gesagt haben, müssen Sie keinen Finalizer implementieren, es sei denn, Sie haben direkt nicht verwaltete Ressourcen. Unter der Annahme, dass Sie in .NET 2.0 oder höher arbeiten, ist es unwahrscheinlich, dass Sie jemals einen Finalizer implementieren müssen, da in der Regel SafeHandle verwendet werden kann, um Ihre nicht verwalteten Ressourcen zu wickeln.
Ich habe a geschrieben Ziemlich langer Blog -Beitrag Abdeckung des Hintergrunds und der Implementierung von idisposabilen und endgültigen Abschlüssen vor einiger Zeit, was eine Lektüre wert sein kann, wenn Sie nicht ganz klar sind.