Domanda: Perché Java / C # non può implementare RAII?
Chiarimento: Sono consapevole che il garbage collector non è deterministico. Pertanto, con le funzionalità linguistiche correnti, non è possibile chiamare automaticamente il metodo Dispose () di un oggetto all'uscita dell'ambito. Ma potrebbe essere aggiunta una caratteristica così deterministica?
Comprensione:
Ritengo che un'implementazione di RAII debba soddisfare due requisiti:
1. La durata di vita di una risorsa deve essere associata a un ambito.
2. Implicito. La liberazione della risorsa deve avvenire senza una dichiarazione esplicita da parte del programmatore. Analogo a un garbage collector che libera memoria senza un'istruzione esplicita. L '"implicità" deve solo accadere al punto di utilizzo della classe. Il creatore della biblioteca di classi deve ovviamente implementare esplicitamente un metodo destructor o Dispose ().
Punto di soddisfazione Java / C # 1. In C # una risorsa che implementa IDisposable può essere associata a un ambito "using":
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
Questo non soddisfa il punto 2. Il programmatore deve legare esplicitamente l'oggetto a uno speciale scope "using". I programmatori possono (e devono) dimenticare di legare esplicitamente la risorsa a un ambito, creando una perdita.
Infatti i blocchi "using" vengono convertiti nel codice try-finally-dispose () dal compilatore. Ha la stessa natura esplicita del modello try-finally-dispose (). Senza una versione implicita, l'hook di un ambito è lo zucchero sintattico.
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!!!
Penso che valga la pena creare una funzionalità linguistica in Java / C # che consenta oggetti speciali che sono agganciati allo stack tramite uno smart-pointer. La funzione consentirebbe di contrassegnare una classe come bound-bound, in modo che venga sempre creata con un hook allo stack. Potrebbero esserci opzioni per diversi tipi di puntatori intelligenti.
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.
Penso che l'implicità sia "ne vale la pena". Proprio come l'implicità della raccolta dei rifiuti è "ne vale la pena". L'uso esplicito di blocchi è rinfrescante per gli occhi, ma non offre alcun vantaggio semantico rispetto a try-finally-dispose ().
È impraticabile implementare tale funzionalità nei linguaggi Java / C #? Potrebbe essere introdotto senza rompere il vecchio codice?