64 votes

Pourquoi n'y a-t-il pas de RAII dans .NET?

Il était avant tout un développeur C++, l'absence de RAII (Acquisition de Ressources Est d'Initialisation) en Java et .NET a toujours dérangé. Le fait que le fardeau de nettoyage est déplacé à partir de la classe de l'écrivain à sa consommation ( try finally ou .NET using construire) semble être nettement inférieur.

Je ne vois pourquoi en Java il n'y a pas de support pour le RAII, puisque tous les objets sont situés sur le tas et le garbage collector, intrinsèquement, ne prend pas en charge déterministe de la destruction, mais dans .NET avec l'introduction de types de valeur (struct) nous ont (apparemment) candidat parfait pour le RAII. Un type de la valeur qui est créée sur la pile a un sens bien défini la portée et destructeur C++ sémantique peut être utilisé. Cependant, le CLR ne permettent pas à un type de valeur afin d'avoir un destructeur.

Mon hasard des recherches a trouvé un argument que, si une valeur est de type boîte , il relève de la compétence de la collecte des déchets et donc sa destruction devient non-déterministe. J'ai l'impression que cet argument n'est pas assez fort, les avantages de la RAII sont assez grands pour dire qu'une valeur de type avec un destructeur ne peut pas être mis en boîte (ou utilisé comme un membre de la classe).

Pour couper une longue histoire courte, ma question est: existe-t-il d'autres raisons de types de valeur ne peut pas être utilisée pour introduire RAII .NET? (ou vous pensez que mon argument sur RAII est évident que les avantages sont défectueux?)

Edit: j'ai pas formulée de la question clairement depuis les quatre premières réponses ont manqué le point. Je sais à propos de Finalize et de sa non-déterministe caractéristiques, je sais à propos de l' using construire et je crois que ces deux options sont inférieures à RAII. using est une chose que la consommation d'une classe doit de rappeler combien de personnes j'ai oublié de mettre un StreamReader en using bloc?). Ma question est philosophique sur le langage de conception, pourquoi est-ce la façon dont il est et peut-il être amélioré?

Par exemple avec un générique de façon déterministe destructibles type de valeur que je peux faire l' using et lock mots-clés redondante (ce qui est réalisable par la bibliothèque de classes):

    public struct Disposer<T> where T : IDisposable
    {
        T val;
        public Disposer(T t) { val = t; }
        public T Value { get { return val; } }
        ~Disposer()  // Currently illegal 
        {
            if (val != default(T))
                val.Dispose();
        }
    }


Je ne peux pas aider, mais à la fin avec un apropos devis que j'ai vu une fois, mais ne peut pas trouver son origine.

Vous pouvez prendre mon déterministe de la destruction lors de mon rhume de main morte, est hors de portée. --Anon

16voto

Adam Wright Points 31715

Un meilleur titre serait "Pourquoi n'est-il pas RAII en C#/VB". C++/CLI (L'évolution de l'avortement qui a été Managed C++) a RAII dans le même sens que C++. C'est tout simplement la syntaxe de sucre pour la même finalisation motif que le reste de la CLI d'utilisation des langues (Destructeurs dans les objets gérés pour le C++/CLI sont effectivement finalisers), mais il est là.

Vous pourriez, comme http://blogs.msdn.com/hsutter/archive/2004/07/31/203137.aspx

14voto

Konrad Rudolph Points 231505

Excellente question, et celui qui m'a gêné considérablement. Il semble que les avantages de la RAII sont perçus très différemment. Dans mon expérience avec .NET, le manque de déterministe (ou au moins fiable) la collecte des ressources est l'un des inconvénients majeurs. En fait, l' .NET m'a forcé à plusieurs reprises à employer l'ensemble des architectures de traiter avec les ressources non managées peut (mais ne pourrait pas) besoin explicite de collecte. Ce qui, bien sûr, est un énorme inconvénient, car il rend l'ensemble de l'architecture de plus en plus difficile et dirige l'attention du client à l'écart de la plus centrale aspects.

14voto

Rasmus Faber Points 24195

Brian Harry a un beau post sur les justifications ici.

Voici un extrait:

Qu'en est déterministe de la finalisation et de types de valeur (les structures)?

-------------- J'ai vu beaucoup de questions sur les structures ayant les destructeurs, etc. Cela vaut la peine commentaire. Il existe une variété de les questions pour expliquer pourquoi certaines langues ne sont pas ont leur.

(1) composition - Ils ne vous donnent pas déterministe de la vie en général cas pour le même type de composition les raisons décrites ci-dessus. Tout non-déterministe de la classe contenant un ne serait pas appeler le destructeur jusqu'à ce qu'il a été finalisé par le conseil d'administration de toute façon.

(2) copie des constructeurs, un lieu unique où il serait vraiment nice est dans pile allouée habitants. Ils seraient l'étendue, la méthode et tout serait grand. Malheureusement, afin d'obtenir cela fonctionne vraiment, vous devez également ajouter la copie de constructeurs et de les appeler chaque fois qu'une instance est copié. C'est l'un des plus laid et le plus complexe de choses sur le C++. Vous vous retrouvez l'obtention du code de l'exécution de tous les coins du lieu où vous ne l'attendez pas. Il causes des bouquets de problèmes de langue. Certaines langues concepteurs ont choisi d' rester à l'écart de cela.

Disons que nous avons créé des structures avec les destructeurs, mais a ajouté un tas de restrictions de rendre son comportement sensible face à des problèmes ci-dessus. Les restrictions seraient quelque chose comme:

(1) Vous pouvez le faire seulement en tant que local les variables.

(2) Vous pouvez uniquement passer par-ref

(3) Vous ne pouvez pas céder, vous ne peut accéder aux champs et appel méthodes sur eux.

(4) Vous ne pouvez pas cocher .

(5) les Problèmes de leur utilisation par Réflexion (liaison tardive) parce que implique généralement la boxe.

peut-être plus, mais c'est un bon début.

À quoi ces choses? Serait vous créez un fichier ou un la connexion à la base de la classe qui peut SEULEMENT être utilisé comme une variable locale? J' ne crois pas que quelqu'un serait vraiment. Ce que vous voulez faire à la place est de créer un objectif général de la connexion, puis créer une auto détruite wrapper pour utiliser comme une étendue variable locale. L' appelant alors choisir ce qu'ils voulu l'utiliser. Remarque l'appelant a fait une décision et il n'est pas entièrement encapsulées dans l'objet lui-même. Étant donné que vous pouvez utiliser quelque chose comme les suggestions à venir dans une couple de sections.

Le remplacement pour le RAII .NET est l'aide-modèle, qui fonctionne presque aussi bien une fois que vous vous habituez à elle.

1voto

leppie Points 67289

Le plus proche de cela est le très limité opérateur stackalloc.

1voto

Si vous les recherchez, il existe des thèmes similaires, mais en gros, il s'agit simplement de mettre en œuvre un type IDisposable si vous souhaitez passer à RAII. .NET et d'utiliser l'instruction "using" pour obtenir une élimination déterministe. De cette manière, bon nombre des mêmes idéaux peuvent être mis en œuvre et utilisés de manière légèrement plus verbeuse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X