Frage: Warum kann Java / C # RAII nicht implementieren?
Klarstellung: Mir ist bewusst, dass der Müllsammler nicht deterministisch ist. Mit den aktuellen Sprachfunktionen ist es daher nicht möglich, dass die Dispose () - Methode eines Objekts beim Verlassen des Gültigkeitsbereichs automatisch aufgerufen wird. Aber könnte ein solches deterministisches Merkmal hinzugefügt werden?
Mein Verständnis:
Ich bin der Meinung, dass eine Implementierung von RAII zwei Anforderungen erfüllen muss:
1. Die Lebensdauer einer Ressource muss an einen Bereich gebunden sein.
2. Implizit. Die Freigabe der Ressource muss ohne ausdrückliche Anweisung des Programmierers erfolgen. Analog zu einem Garbage Collector, der Speicher ohne explizite Anweisung freigibt. Die "implizite Aussage" muss nur am Verwendungsort der Klasse erfolgen. Der Klassenbibliothek-Ersteller muss natürlich explizit einen Destruktor oder eine Dispose () -Methode implementieren.
Java / C # -erfüllungspunkt 1. In C # kann eine Ressource, die IDisposable implementiert, an einen Gültigkeitsbereich "using" gebunden werden:
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
Dies erfüllt Punkt 2 nicht. Der Programmierer muss das Objekt explizit an einen speziellen Verwendungsbereich binden. Programmierer können (und müssen) vergessen, die Ressource explizit an einen Bereich zu binden, wodurch ein Leck entsteht.
Tatsächlich werden die using-Blöcke vom Compiler in try-finally-dispose () - Code konvertiert. Es hat die gleiche explizite Natur des try-finally-dispose () - Musters. Ohne eine implizite Freigabe ist der Haken zu einem Bereich syntaktischer Zucker.
void test()
{
//Programmer forgot (or was not aware of the need) to explicitly
//bind Resource to a scope.
Resource r = new Resource();
r.foo();
}//resource leaked!!!
Ich denke, es lohnt sich, ein Sprachfeature in Java / C # zu erstellen, das spezielle Objekte ermöglicht, die über einen Smart-Pointer mit dem Stack verknüpft sind. Mit dieser Funktion können Sie eine Klasse als bereichsgebunden kennzeichnen, sodass sie immer mit einem Haken zum Stapel erstellt wird. Es könnte Optionen für verschiedene Arten von intelligenten Zeigern geben.
class Resource - ScopeBound
{
/* class details */
void Dispose()
{
//free resource
}
}
void test()
{
//class Resource was flagged as ScopeBound so the tie to the stack is implicit.
Resource r = new Resource(); //r is a smart-pointer
r.foo();
}//resource released on scope exit.
Ich denke, implizite Aussagen sind es "wert". Genau so, wie es sich "lohnt", Müll zu sammeln. Explizite Verwendung von Blöcken erfrischt die Augen, bietet jedoch keinen semantischen Vorteil gegenüber try-finally-dispose ().
Ist es unpraktisch, eine solche Funktion in Java / C # -Sprachen zu implementieren? Könnte es eingeführt werden, ohne alten Code zu brechen?
using
die Ausführung der Dispose
ist garantiert (na ja, den Prozess Diskontierung plötzlich ohne Ausnahme Sterben geworfen, an welcher Stelle alle Bereinigungs vermutlich strittig wird).
struct
), diese wird jedoch in der Regel vermieden, es sei denn, es handelt sich um sehr spezielle Fälle. Siehe auch .
Dispose
s wird immer ausgeführt, unabhängig davon , wie sie ausgelöst sind. Das Hinzufügen einer impliziten Zerstörung am Ende des Geltungsbereichs hilft dem nicht.