Aufruf von Destruktoren in C# **gelöst**



  • Destiniy schrieb:

    also ist es in C# auch generell so wenn ich ein Objekt mit new instanziiere, dann muß ich auch ein Dispose auf dieses Objekt machen?

    MfG

    Nein.

    Wenn Du in C# ein Object instanziierst das IDispose implementiert hat dann solltest Du auch Dispose aufrufen.

    An der Stelle wäre es dringend geraten Dir mal die Grundlagen der GC anzulesen...



  • Nicht nur Grundlagen über den GC, über alles...



  • Und bitte hört auf Finalizer bzw. Dispose-Funktionen als Destruktor zu bezeichnen.

    Finalizer, Dispose und Destruktor sind drei ziemlich unterschiedliche Dinge.



  • Hier noch Links zu den besagten drei Themen:
    http://msdn.microsoft.com/en-us/library/498928w2.aspx
    http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
    http://msdn.microsoft.com/en-us/library/ms177197.aspx
    http://www.codeproject.com/KB/mcpp/cppclidtors.aspx

    Und eine Zusammenstellung der etwas verwirrenden Ausdrücken und Syntax:

    IDisposable
    C++/CLI: ~ClassName() bewirkt via Kompiler ein automatisches Implementieren der IDisposable Schnittstelle mit der Dispose() Methode.
    (Ein explizites Ableiten von IDisposable führt zu einem Kompilier- Fehler.)

    C#: Das äquivalente in C# ist es die IDisposable Schnittstelle zu implementieren.

    Finalizer
    C++/CLI: !ClassName() bewirkt via Kompiler, dass die Finalize() Methode überschrieben wird.

    C#: ~ClassName() bewirkt via Kompiler, dass die Finalize() Methode überschrieben wird.
    (Ein explizites überschreiben von Finalize() führt zu einem Kompilier- Fehler.)

    Unglücklicherweise wird sowohl in C# als auch in C++/CLI bei ~ClassName() oft von Destruktor gesprochen, obwohl das Verhalten nicht den Destruktoren von ISO C++ entspricht.

    Simon



  • Unglücklicherweise wird sowohl in C# als auch in C++/CLI bei ~ClassName() oft von Destruktor gesprochen, obwohl das Verhalten nicht den Destruktoren von ISO C++ entspricht.

    Jopp. Und noch unglücklicher finde ich den Umstand, dass C# und C++ unter ~ClassName() was unterschiedliches verstehen 👎
    (wie ja auch aus deinem Beitrag hervorgeht)
    Verwirrte Anfänger sind da vorprogrammiert.

    (Und es ist auch für erfahrene Programmierer nicht angenehm, kann man schonmal drüber stolpern.)

    Umso wichtiger finde ich es immer den richtigen Ausdruck zu verwenden, wenn man irgendwo was diskutiert, was mit Dispose-Funktionen, Finalizern und/oder Destruktoren zu tun hat.



  • erstmal danke für die Links.

    ich habe jetzt in meinem C++/ClI Code den finalizer implementiert, dadurch ruft der GC den dann auch automatisch.



  • Destiniy schrieb:

    erstmal danke für die Links.

    ich habe jetzt in meinem C++/ClI Code den finalizer implementiert, dadurch ruft der GC den dann auch automatisch.

    Dispose solltest Du dennoch aufrufen.



  • theta schrieb:

    Dispose solltest Du dennoch aufrufen.

    Nein, brauchst Du nicht zu machen....

    http://stackoverflow.com/questions/867114/why-no-reference-counting-garbage-collection-in-c

    Lies Dir das mal bitte bis zum Ende genau durch.



  • davon bin ich auch ausgegangen, da der GC ja genau die Funktion hat



  • Fred F. schrieb:

    theta schrieb:

    Dispose solltest Du dennoch aufrufen.

    Nein, brauchst Du nicht zu machen....

    http://stackoverflow.com/questions/867114/why-no-reference-counting-garbage-collection-in-c

    Lies Dir das mal bitte bis zum Ende genau durch.

    Widerspruch.

    Wenn es ein explizites Dispose gibt sollte man das aufrufen. Der Sinn des Dispose liegt gerade darin unmanaged und/oder begrenzte Resourcen wieder freizugeben sobald man sie nicht mehr braucht. Da man nicht weis wann, genaugenommen ncihtmal _ob_ die GC ein Object aufräumt können so wichtige Resourcen wie z.B. files blokiert durch die GC blokiert werden.

    Was man _nicht_ braucht ist für jede Klasse IDisposeable zu implementieren, sondern nur für solche KLassen, bei denen eben jene unmanaged und/oder begrenzten Resourcen benutzt werden.

    On a sidenode.

    Der oben gelinkte Artikel ist sehr ungenau. Dispose ist kein Ersatz für den Destructor so wie es da eingangs dargestellt wird, sondern ein Pattern um ein Problem der GC zu lösen.



  • Genau.
    Das Problem ist ja nicht der Speicher des Objekts welches IDisposable implementiert. Das Problem sind die "unmanaged" Resourcen wie File-Handles, Datenbank-Connections, Fenster-Handles etc.
    Wenn du nicht Dispose aufrufst, dann werden diese Dinge eben erst irgendwann mal freigegeben.

    Bei Files kann das dann z.B. dazu führen, dass du irgendwelche Files nicht aus anderen Programmen öffnen/umbenennen/schreiben/löschen kannst, nur weil du irgendwann mal von Programm X aus auf dieses File zugegriffen hattest, und Programm X noch läuft.

    Bei Datenbank-Connections/Recordsets/... kann es dazu führen dass die Performance des Datenbank-Server in die Knie geht, weil der auf einmal tausende Connections sieht -- auch wenn dein Programm bloss immer eine verwendet.

    Und bei anderen Resourcen kann es schlicht und einfach sein, dass sie "ausgehen". Es gibt z.B. nur endlich viele Window-Handles. Wenn ein Programm zu viele Window-Handles "ansammelt" (weil es seine Fenster nicht sauber disposed), kann es sein, dass irgendwann mal irgendwo einfach Buttons/Texte/... oder gar ganze Fenster "fehlen", weil das System keine Handles mehr frei hat.



  • Man sollte eben Wissen warum man wie welche Funktion nutzt.
    Ein paar PEN oder SolidBrush ohne Dispose und schon kann man Probleme haben.


Anmelden zum Antworten