Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Dispose für jede Klasse implementieren?

Moderationshinweis von gfoidl (25.11.2011 - 19:16)

Abgeteilt von Dispose implementieren und verwenden (IDisposable)

norman_timo
myCSharp.de - Member

Avatar #avatar-1775.jpeg


Dabei seit:
Beiträge: 4.506
Herkunft: Wald-Michelbach (Odw)

Themenstarter:

beantworten | zitieren | melden

Hallo zusammen,

habe jüngst ein Kollege gesehen, der für JEDE Klasse das IDisposable umgesetzt hat, im Dekonstruktor dementsprechend Dispose aufgerufen hat, und im Dispose den GC um Aufräumen gebeten hat.

Angeblich soll das einen beschleunigten Speicherabbau forcieren.

Ich habe ihm gesagt, solange es sich nicht um unmanged Ressourcen handelt, soll er das sein lassen. Ich gab ihm folgende Begründung mit:
Der GC räumt auf wenn es sein muss. Mag sein, dass ein .NET Programm zunächst mehr Speicher frisst als ein sagen wir C++ Programm. Das liegt nur daran, dass der GC weiß ob es zur Zeit nötig ist Speicher freizugeben oder ob man nicht lieber das Programm arbeiten lassen kann.

Ich stellte dann folgende Regel auf:
Unmanaged Ressourcen werden verwendet: IDisposable umsetzen
Nur Managed Ressourcen: Kein IDisposable

Ich denke damit fährt man ganz gut und liefert die optimale Performance.

Grüße
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
private Nachricht | Beiträge des Benutzers
Golo Roden
myCSharp.de - Member

Avatar #avatar-2167.png


Dabei seit:
Beiträge: 4.207
Herkunft: Riegel am Kaiserstuhl

beantworten | zitieren | melden

Zitat von norman_timo
habe jüngst ein Kollege gesehen, der für JEDE Klasse das IDisposable umgesetzt hat, im Dekonstruktor dementsprechend Dispose aufgerufen hat, und im Dispose den GC um Aufräumen gebeten hat.

Angeblich soll das einen beschleunigten Speicherabbau forcieren.

Das ist totaler Blödsinn, denn wenn man für jede Klasse einen Finalizer implementiert, verbleiben die Objekte länger (!) im Speicher als ohne, da der GC sie nicht direkt abräumen kann, sondern sie erst noch in die Finalizable-Queue stecken muss.
Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de
private Nachricht | Beiträge des Benutzers
norman_timo
myCSharp.de - Member

Avatar #avatar-1775.jpeg


Dabei seit:
Beiträge: 4.506
Herkunft: Wald-Michelbach (Odw)

Themenstarter:

beantworten | zitieren | melden

Hallo Golo,

vielen Dank, ich weiß dass es Unsinn ist, aber nun hab ich auch eine fundierte Begründung warum ;-) (Hab das nicht näher analysiert).

Grüße
Norman-Timo
A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”
private Nachricht | Beiträge des Benutzers
0815Coder
myCSharp.de - Member



Dabei seit:
Beiträge: 767

beantworten | zitieren | melden

Zitat von Golo Roden
Zitat von norman_timo
habe jüngst ein Kollege gesehen, der für JEDE Klasse das IDisposable umgesetzt hat, im Dekonstruktor dementsprechend Dispose aufgerufen hat, und im Dispose den GC um Aufräumen gebeten hat.

Angeblich soll das einen beschleunigten Speicherabbau forcieren.

Das ist totaler Blödsinn, denn wenn man für jede Klasse einen Finalizer implementiert, verbleiben die Objekte länger (!) im Speicher als ohne, da der GC sie nicht direkt abräumen kann, sondern sie erst noch in die Finalizable-Queue stecken muss.

nicht nur das. dadurch arbeitet der GC auch wesentlich langsamer, weil er mehr objekte prüfen muss.
loop:
btst #6,$bfe001
bne.s loop
rts
private Nachricht | Beiträge des Benutzers
svenson
myCSharp.de - Member



Dabei seit:
Beiträge: 8.746
Herkunft: Berlin

beantworten | zitieren | melden

Ich möchte nochmal das bekräftigen, was Golo zum Finalizer sagte. Der Fehler, einen Finalizer zu implementieren ist einer der häufigsten überhaupt und kann sehr unangenehmen Einfluss auf das Laufzeitverhalten haben. Wenn man also nur Dispose auf den Membern aufrufen möchte, dann keinen Finalizer implementieren sondern nur IDisposable.

Hier ein sehr erschöpfendes Blog:

DG Update: Dispose, Finalization, and Resource Management
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo svenson,

auch wenn ein Finalizer Performance kostet, IDisposable ist nach den Richtlinien von MS (und dem Sinn von Dispose nach) nur dann richtig implementiert, wenn Dispose auch aus dem Finalizer aufgerufen wird. Das ist eine feststehende Tatsache. Was anderes ist es, wenn man IDisposable nicht implementiert. Dann sollte man überlegen, ob man überhaupt einen Finalizer braucht. Meistens braucht man ihn dann nicht.

herbivore
private Nachricht | Beiträge des Benutzers
svenson
myCSharp.de - Member



Dabei seit:
Beiträge: 8.746
Herkunft: Berlin

beantworten | zitieren | melden

Zitat von herbivore
IDisposable ist nach den Richtlinien von MS (und dem Sinn von Dispose nach) nur dann richtig implementiert, wenn Dispose auch aus dem Finalizer aufgerufen wird.

Das stimmt, aber nur unter der Vorraussetzung, dass ein Finalizer existiert. Einen Finalizer brauche ich, wenn unmanaged Ressourcen direkt verwalte. Mittels IDisposable kann ich die Freigabe zusätzlich aktiv machen.

Es macht aber auch in anderen Fällen Sinn, IDisposable zu implementieren, z.B. wenn man nur managed Ressourcen aktiv freigeben will. Hier brauche ich keinen Finalizer, weil die Finalizer bzw. Dispose der Member automatisch aufgerufen werden. Und seit es SafeHandle gibt, ist dieser Fall eigentlich der Standardfall. Und dann sollte eben kein Finalizer implementiert werden. In der Praxis vermutlich selten kritisch, aber wenn man sehr viele Objekte erzeugt, kann sich der unnötige Finalizer sehr unschön auswirken.

Ausnahme von dieser Regel: Man braucht ebenfalls einen Finalizer, wenn die Basisklasse einen Finalizer implementiert.

Beim Umgang mit BS-Ressourcen kann man eigentlich sagen: Für jeden Ressourcentypen eine SafeHandle-Klasse ableiten. Damit kann man auf Finalizer komplett verzichten. IDisposable implementieren, wo aktive Freigabe erwünscht. Bei unmanaged Ressourcen die nicht Zeiger/Handle-basiert arbeiten, muss man in den Finalizer-Apfel beissen.
Dieser Beitrag wurde 12 mal editiert, zum letzten Mal von svenson am .

Moderationshinweis von herbivore (25.11.2011 - 19:30)

Wenn die Basisklasse einen Finalizer hat, braucht die Unterklasse keinen eigenen zu implementieren, denn der Finalizer (der Oberklasse) macht ja eh nichts anderes als Dispose (false); aufzurufen. Das muss in der Unterklasse nicht nochmal erfolgen. Stattdessen kann die Unterklasse bei Bedarf Dispose (bool) überschreiben.

private Nachricht | Beiträge des Benutzers