Question: Pourquoi Java / C # ne peut-il pas implémenter RAII?
Clarification: je sais que le ramasse-miettes n'est pas déterministe. Ainsi, avec les fonctionnalités actuelles du langage, il n'est pas possible d'appeler automatiquement la méthode Dispose () d'un objet à la sortie de la portée. Mais pourrait-on ajouter une telle caractéristique déterministe?
Ma compréhension:
Je pense qu'une implémentation de RAII doit satisfaire deux exigences:
1. La durée de vie d'une ressource doit être liée à une étendue.
2. Implicite. La libération de la ressource doit avoir lieu sans déclaration explicite du programmeur. Analogue à un garbage collector libérant de la mémoire sans déclaration explicite. L '«implicitness» ne doit se produire qu'au point d'utilisation de la classe. Le créateur de la bibliothèque de classes doit bien sûr implémenter explicitement un destructeur ou une méthode Dispose ().
Java / C # satisfait le point 1. En C #, une ressource implémentant IDisposable peut être liée à une étendue "using":
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
Cela ne satisfait pas le point 2. Le programmeur doit lier explicitement l'objet à une portée spéciale "using". Les programmeurs peuvent (et oublient) de lier explicitement la ressource à une étendue, créant une fuite.
En fait, les blocs "using" sont convertis en code try-finally-dispose () par le compilateur. Il a la même nature explicite que le modèle try-finally-dispose (). Sans libération implicite, l'hameçon à une portée est le sucre syntaxique.
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!!!
Je pense qu'il vaut la peine de créer une fonctionnalité de langage en Java / C # permettant des objets spéciaux qui sont accrochés à la pile via un pointeur intelligent. La fonctionnalité vous permettrait de marquer une classe comme liée à la portée, afin qu'elle soit toujours créée avec un crochet à la pile. Il pourrait y avoir des options pour différents types de pointeurs intelligents.
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.
Je pense que l'implicitation en vaut la peine. Tout comme l'implication de la collecte des ordures en "vaut la peine". L'utilisation de blocs explicites est rafraîchissante pour les yeux, mais n'offre aucun avantage sémantique par rapport à try-finally-dispose ().
Est-il impossible d'implémenter une telle fonctionnalité dans les langages Java / C #? Pourrait-il être introduit sans casser l'ancien code?
using
l'exécution de Dispose
est garanti (enfin, actualiser le processus en train de mourir soudainement sans exception, à ce moment-là, tout nettoyage devient vraisemblablement théorique).
struct
), mais ils sont généralement évités , sauf dans des cas très particuliers. Voir aussi .
Dispose
s sont jamais exécutées, la façon dont ils sont déclenchés. L'ajout d'une destruction implicite à la fin de la portée n'aidera pas cela.