2009-03-07 8 views

Antwort

9

Es gibt immer eine Finalizerthread in IL - System.Object.Finalize() in jeder Klasse vorhanden ist, so dass, wenn Sie eine benutzerdefinierte Klasse machen, hat es eine Finalizerthread Sie unterdrücken wollen. Nichtsdestoweniger werden nicht alle Objekte in die Finalisierungswarteschlange gestellt, sodass Sie die Finalisierung nur technisch unterdrücken sollten, wenn Sie Ihren eigenen Finalizer implementieren.

Wenn Sie IDisposable implementieren, um nicht verwaltete Ressourcen zu verpacken, sollten Sie einen Finalizer hinzufügen, und Sie sollten dies verhindern, da Sie die Bereinigung theoretisch bereits durchführen, wenn Dispose aufgerufen wird.

+0

Wahr. Außerdem sollten Sie einen Finalizer haben, der Dispose() aufruft. – configurator

+0

TrueObject.Finalize ist ein Null-Op., Aber wenn Sie IDisposable implementieren, sagen Sie, dass Sie Ressourcen zum Freigeben haben. Von MSDN bedeutet das, dass Sie immer einen Finalizer haben sollten, um sie zu befreien, damit sie korrekt behandelt werden. Dies bedeutet, dass Sie den Finalize-Aufruf "Dispose" und "Dispose" die Finalisierung beenden müssen. –

+4

@configurator Sie sollten nur einen Finalizer haben, wenn Sie direkt über nicht verwaltete Ressourcen verfügen (z. B. Handles). Wenn Sie sie nur indirekt besitzen, z.B. ein Verweis auf einen FileStream, warum sollten Sie mehr als IDisposable.Dispose() schreiben {if (fs! = null) {fs.Dispose(); fs = null; }}? IMO, StyleCop ist ein schreckliches Werkzeug, das eine Menge nutzlosen Text zu schreiben und zu pflegen zwingt, und fügt keinen Geschäftswert im Gegenzug. –

2

Alle Objekte haben eine Finalizer-Methode, auch wenn Sie keine implementiert haben, indem Sie einen C# -Destruktor verwenden (der nicht wirklich vom GC aufgerufen wird). Wenn Sie IDisposable implementiert haben, sollten Sie den Anruf einfach unterdrücken, da Sie sich entschieden haben, die Finalisierung explizit durchzuführen.

devx article

+0

Können Sie die "nicht garantiert von GC genannt werden" erklären? –

+0

Während der Programmbeendigung erhalten einige Objekte möglicherweise keine Chance, ihre Finalizer auszuführen, wenn die Bereinigung zu lange dauert. Das könnte sein, worauf er sich bezieht. –

+0

Ja, darauf habe ich mich bezogen. – x0n

2

Ich sehe keine Notwendigkeit, SuppressFinalize() aufzurufen, wenn kein Finalizer definiert ist. Wenn Sie defensiv sein wollen, kann es gut sein, einen Finalizer sowie Dispose() zu haben, so dass Sie nicht darauf angewiesen sind, dass Clients immer Dispose() aufrufen. Dann werden Sie keine Ressourcen verlieren, wenn sie es vergessen.

+0

Wenn ein Objekt für andere IDisposable-Objekte "verantwortlich" ist, aber über keine verwalteten Ressourcen verfügt, benötigt es Dispose, aber keinen Finalizer. –

20

Es gibt keine Notwendigkeit GC.SuppressFinalize(this) in Entsorgen Sie anrufen, es sei denn:

  • Sie die Basisklasse, die für das Überschreiben (wieder virtuelle Entsorgen Methoden bestimmt implementiert, ist es vielleicht nicht Ihrer Verantwortung auch hier, aber Sie möchten vielleicht um es in diesem Fall zu tun)
  • Sie haben einen Finalizer selbst. Technisch hat jede Klasse in .NET einen Finalizer, aber wenn die einzige Finalizerthread vorhanden derjenige in Object ist, dann wird das Objekt nicht brauchen Finalisierung betrachtet und nicht

mich auf GC auf der Finalisierung Liste setzen würde sagen, vorausgesetzt, Sie haben keine der oben genannten Fälle, dass Sie diese Nachricht ignorieren können.

+1

Wann sollte eine abgeleitete Klasse * EVER * einen Finalizer zu einer nicht-trivialen Basisklasse hinzufügen? Warum Code hinzufügen, damit eine abgeleitete Klasse etwas tun kann, was sie niemals tun sollte? – supercat

+0

@supercat Wenn eine abgeleitete Klasse nicht verwaltete Ressourcen besitzt, sollte sie über einen Finalizer verfügen, um sicherzustellen, dass sie freigegeben werden. Wenn das Objekt immer korrekt verwendet wird (mit try-finally oder äquivalent einer using-Anweisung), führt Dispose die Bereinigung durch und unterdrückt den Finalizer. Der Finalizer stellt jedoch sicher, dass die nicht verwalteten Ressourcen schließlich freigegeben werden (wenn das Objekt als Garbage Collection erfasst wird). auch wenn Dispose nie aufgerufen wurde (zB wegen einer Ausnahme und fehlendem Schutz eines Codeblocks). –

+1

@TheDag: Jede nicht verwaltete Ressource, die Finalizer-Bereinigung benötigt, sollte fast immer in einem eigenen Objekt eingekapselt werden, das entweder von "Object" oder einem abstrakten Basistyp abgeleitet sein sollte, der explizit für diese Bereinigung entwickelt wurde. Der resultierende Typ wäre dann eine verwaltete Ressource, auf die der größere Typ verweisen könnte. Die Bereinigung der Finalisierung würde durch das kleinere einkapselnde Objekt erledigt werden; Das größere Objekt würde keinen Finalizer benötigen. – supercat