Ich werde gebeten, IDisposable für Objekte zu implementieren, die zu 100% verwaltete Ressourcen sind, die keine Streams und keine großen Ressourcen enthalten.
Ich verstehe, wie wichtig es ist, große und nicht verwaltete Ressourcen ordnungsgemäß zu entsorgen, aber was ist mit der anderen Seite der Gleichung?
Für ein Objekt, das nicht von der Implementierung von IDisposable profitiert (kleine, vollständig verwaltete Objekte) Welche negativen Auswirkungen kann GC.SuppressFinalize haben, wenn überhaupt?
Kommentare
- Sieht nach vorzeitiger Optimierung aus. Können Sie die Person, die Sie dazu aufgefordert hat, nach den Ergebnissen fragen, die sie durch Profilerstellung und Benchmarking erhalten hat und die zeigen, dass das Hinzufügen von
IDisposable
in diesem Fall den Speicherbedarf verbessert? - @MainMa Nein, aber das ' hat mich nicht davon abgehalten, sowieso zu fragen. Das Ergebnis war eine 5-minütige Antwort von " es ist genau so, wie wir es ' immer getan haben, Sie tun es auch ".
- Nun, es ist möglich,
IDisposable
zu implementieren, ohne einen Destruktor / Finalizer zu schreiben. Ich ' weiß nicht, ob die Person, die Sie gebeten hat,IDisposable
zu implementieren, meinte, Sie sollten auch einen Destruktor erstellen. Wenn die Klasse keinen Destruktor hat, hatGC.SuppressFinalize
natürlich keinen Sinn. Wenn die Klasse über einen Destruktor verfügt, müssen SieGC.SuppressFinalize(this)
angeben, wenn IhreDispose
-Methode ausgeführt wurde. Andernfalls wird die Instanz nicht einfach durch Müll gesammelt, sondern in einer Finalizer-Warteschlange in die Warteschlange gestellt und nur in einer Sammlung der Generation 2 gesammelt. - @JeppeStigNielsen Die Frage besagt, dass die Objekte vollständig verwaltet werden Ressourcen, sodass ' kein Finalizer erforderlich ist. Wenn einer da ist, wissen wir, dass ' falsch ist.
Antwort
Das einzige Ziel von GC.SuppressFinalize
ist:
, um zu verhindern, dass der Finalizer nicht verwaltete Ressourcen freigibt, die wurden bereits von der IDisposable.Dispose-Implementierung freigegeben.
Sobald Sie das Objekt entsorgt haben, sollten Sie tatsächlich GC.SuppressFinalize(this);
aufrufen, wie in eine Antwort auf die Frage gezeigt. “ Wann sollte ich GC.SuppressFinalize () verwenden? „. Die Code-Analyse „ CA1816 ist ebenfalls nützlich.
Jetzt wird die Implementierung von IDisposable
aktiviert Objekte, die keine nicht verwalteten Ressourcen haben, sehen ziemlich seltsam und fragwürdig aus. Da der einzige Grund, den die Person Ihnen gegeben hat, war: „Es ist genau so, wie wir es immer getan haben, Sie tun es auch“, anstatt Profilierungs- / Benchmarking-Daten bereitzustellen, die zeigen, dass das Hinzufügen von IDisposable
wird in einem bestimmten Fall etwas verbessern, es gibt keine tatsächlichen Gründe dafür.
Würde es Leistungsprobleme verursachen? Schwer zu sagen: Es würde von einem bestimmten Fall abhängen.
Würde Natürlich verursacht es andere Probleme. Ohne die Tatsache zu berücksichtigen, dass die Implementierung von IDisposable
schmerzhaft ist, wird der Code unlesbar und kann nicht mehr gewartet werden, wenn diese Vorgehensweise zu häufig angewendet wird:
public int ComputePrice(Rebate rebate) { using (var currentCurrency = this.User.FindCurrency()) { using (var priceWithoutRebate = this.GetPurePrice()) { using (var canApplyRebate = rebate.CanApplyTo(this)) { if (!canApplyRebate) { return priceWithoutRebate; } using (var priceWithRebate = priceWithoutRebate.Apply(rebate)) { return priceWithRebate; } } } } }
Kommentare
- Nun, ich glaube, die Geschichte ist, dass sie vor langer Zeit eine Verbindung hatten / Probleme mit Stream-Lecks, wahrscheinlich aufgrund von undichtem ADO.NET-Code für Verbindungen / Befehle, und dies verursachte massive Ressourcenlecks. Sie wussten, dass die Implementierung von IDisposable für alles das Problem lösen würde, also taten sie es und es funktionierte. Und jetzt j ust implementieren Sie es auf den meisten Objekten.
- @AndrewHoffman: Es scheint eine plausible Erklärung zu sein. ' rechtfertigt die derzeitige Vorgehensweise jedoch nicht.
Antwort
Sie müssen nicht das schwergewichtige („schmerzhafte“) Dispose + Finalizer-Muster für eine IDisposable-Klasse verwenden, , wenn Die Klasse ist versiegelt und die Klasse verfügt über keine nicht verwalteten Ressourcen.
In dieser Situation können Sie eine Teilmenge des Dispose + Finalizer-Musters verwenden, das nur public Dispose()
hat keinen Finalizer und die Klasse ist versiegelt.
Der Grund für das Versiegeln der Klasse besteht darin, die Probleme zu vermeiden: „Was ist, wenn eine untergeordnete Klasse nicht verwaltete Ressourcen hat?“ und „Was ist, wenn eine untergeordnete Klasse in Zukunft über nicht verwaltete Ressourcen verfügt?“
Joe Duffy, ehemals Microsoft, hat einen langen Artikel (über 30 Seiten), in dem erläutert wird, wie und alle Implementierungen von Permutationsuntergruppen.
Zu dem Artikel gehören Herb Sutter, Brian Grunkemeyer, Jeff Richter und andere C # -Leuchten. Der Artikel ist viel ausführlicher als das, was auf MSDN präsentiert wird.
Leider hat die neue Blog-Engine von Joe Duffy den Originalartikel aus dem Jahr 2005 nicht gut erhalten, daher sieht sie etwas durcheinander aus. Hier ist der Link: http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/
Ich wünschte, ich könnte mein MS-Word-Dokument, das den gesamten Artikel von Joe Duffy enthält, viel besser anhängen Format. 🙁