new
-
Hi Leute,
Ich erstelle in einer Funktion mit new eine Instanz.
Warum wird beim beenden der nicht automatisch der Destructor der Klasse aufgerufen und das Objekt gelöscht.Die Klasse ist eine Datenbankklasse. Es wird mir bei jedem AUfrufen dann ein neuer Connect zur Datenbank aufgebaut.
MySQLDatabase cls = new MySQLDatabase();
-
Mit new jetzt (fehlt im Code)? Damit wird es auf dem Heap angelegt und erst beim Aufruf von delete destruiert. Es ist damit das selbe wie bei Standard C++.
Wenn du ein Objekt auf dem GC-Heap anlegen möchtest, musst du gcnew verwenden. Damit hast du aber auch keine automatische Destruktion am Ende des Blocks, denn der GC arbeitet, wann er es für richtig hält.
Wenn du deterministische Destruktion willst, kannst du in C++ auf auto_ptr zurückgreifen oder die Instanz lokal anlegen. In C# gibt es dafür das using-Statement und finally. Ob das in C++/CLI mit übernommen wurde, weiß ich nicht.
-
Klar mit new. War ein Schreibfehler.
Habe vergessen zusagen: Es handelt sich um C# und nicht mananged C++.
-
Der GC zerstört dein Objekt irgendwann. Wenn du es am Ende eines Blocks zerstören willst, musst du es in einem finally-Block oder in einem using-Statement unterbringen.
using Bitmap = System.Drawing.Bitmap; private void foo() { using( Bitmap x = new Bitmap(...) ) { ... // mach was mit dem Bild } // Hier wird x.Dispose() in jedem Fall aufgerufen }
Achtung: Der Destruktor ~Klasse ist nicht für die deterministische Destruktion zuständig. Dieser wird nur aufgerufen, wenn der GC das Objekt frisst und ist damit die letzte Sicherheit, dass die Resourcen bei einem Programm (was ja lange laufen kann) irgendwann freigegeben werden. Die Klasse sollte also immer so aussehen:
class Klasse : System.IDisposable { public void Dispose() { ... // Resourcen aufräumen System.GC.SuppressFinalize(this); // Jetzt wird ~Klasse nicht mehr aufgerufen } ~Klasse() { Dispose(); } }
Wobei Dispose() eben nach Möglichkeit aufgerufen werden sollte, entweder implizit in einem using-Statement oder explizit in finally.
-
Danke. Habs anderen gelöst. Ich schließe einfach den Socket und lassen die GC seine arbeit verrichten wenn sie es für nötig hält.
-
Hm, mal ne Frage: die Methode Dispose() is in C# ja so ein Art Dtor, mit der Ressourcen aufgeräumt werden können. Aber das Objekt selbst besteht doch weiterhin auf dem Heap. Ich könnte nach einem Aufruf von Dispose() wieder andere Methoden (z.B. CreateResource() ) aufrufen, oder sehe ich das falsch?
-
Richtig, den Speicher, den das Objekt belegt, kannst du nicht freigeben, das kann nur der GC. In Dispose() kannst du aber z.B. Netzwerkverbindungen beenden, Datei-Handles schließen und andere Aufräumarbeiten machen. Dinge, die halt wichtig sind. Speicher ist nicht wichtig, das kann der GC perfekt machen.
Um anzuzeigen, dass eine Klasse kritische Resourcen nutzt, sollte man dann IDisposable verwenden, das erlaubt es einen auch, das Ding in einem using-Statement zu benutzen. Außerdem sollte man Object.Finalize() redefinieren, so dass es Dispose() aufruft, wie in meinem Beispiel gezeigt. (~Klasse ist in C# Object.Finalize(), ich finde die Syntax schlecht gewählt, weil sie C++ Programmierer verwirrt, weil eigentlich Dispose() der C++-Destruktor wäre). Dies sorgt auch auf Klassendesign-Ebene dafür, dass selbst ein DAU-Programmierer die Klasse nicht mehr völlig falsch benutzen kann.
Ob du bei einem dispostem Objekt wieder Methoden aufrufen kannst, hängt von dir ab. CreateResource() sollte eine Exception werfen, wenn das Objekt disposed ist.
Es ist auch sehr wichtig, zu beachten, dass ein Objekt wieder lebendig werden kann. Wenn der Programmierer vergisst, Dispose() aufzurufen und es irgendwann der GC macht, ist das Objekt wohl nicht referenziert. Im Destruktor lässt sich aber Code schreiben, der das Objekt wieder referenziert werden lässt. Wenn das Objekt dann irgendwann wieder nicht mehr referenziert ist, wird ~Klasse nicht mehr aufgerufen, außer man reregistriert das Objekt explizit beim GC. Im Allgemeinen sollte das aber eher selten der Fall sein, dass der Destruktor das Objekt wieder ins Leben zurückruft. IMHO ist es sogar schlechter Stil.