En C #, l' using
instruction est utilisée pour disposer de manière déterministe des ressources sans attendre le garbage collector. Par exemple, il peut être utilisé pour:
Éliminer les commandes ou connexions SQL,
Fermer les flux, libérer la source sous-jacente comme un fichier,
Éléments GDI + gratuits,
etc.
J'ai remarqué que cela using
est de plus en plus utilisé dans les cas où il n'y a rien à disposer, mais où il est juste plus pratique pour l'appelant d'écrire un using
bloc plutôt que deux commandes distinctes.
Exemples:
MiniProfiler , écrit par l'équipe Stack Overflow, utilise
using
pour désigner les blocs à profiler:using (profiler.Step("Name goes here")) { this.DoSomethingUseful(i - 1); }
Une approche alternative serait d'avoir deux blocs:
var p = profiler.Start("Name goes here"); this.DoSomethingUseful(i - 1); profiler.Stop(p);
Une autre approche consisterait à utiliser des actions:
profiler.Step("Name goes here", () => this.DoSomethingUseful(i - 1));
ASP.NET MVC a également choisi
using
pour les formulaires:<% using (Html.BeginForm()) { %> <label for="firstName">Name:</label> <%= Html.TextBox("name")%> <input type="submit" value="Save" /> <% } %>
Une telle utilisation est-elle appropriée? Comment le justifier, compte tenu de plusieurs inconvénients:
Les débutants seraient perdus, car une telle utilisation ne correspond pas à celle qui est expliquée dans les livres et les spécifications linguistiques,
Le code doit être expressif. Ici, l'expressivité souffre, car l'utilisation appropriée de
using
est de montrer que derrière, il y a une ressource, comme un flux, une connexion réseau ou une base de données qui doit être libérée sans attendre le garbage collector.
la source
using
: Cette dernière instruction (par exempleprofiler.Stop(p)
) n'est pas garantie d'être exécutée face aux exceptions et au flux de contrôle.Réponses:
Votre dernière déclaration - que «l'utilisation appropriée de l'utilisation est de montrer que derrière, il y a une ressource, comme un flux, une connexion réseau ou une base de données qui doit être libérée sans attendre le garbage collector» est incorrecte, et la raison pour laquelle est donnée dans la documentation de l'interface IDisposable: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
Donc, si votre classe utilise des ressources non gérées, peu importe que vous souhaitiez ou non que GC se produise - cela n'a rien à voir avec GC car les ressources non gérées ne sont pas GC ( https: // stackoverflow. com / questions / 3607213 / qu'est-ce-que-signifie-géré-par-ressources-non-gérées-en-net ).
Donc, le but de "l'utilisation" n'est pas d'éviter d'attendre sur GC, c'est de forcer la libération de ces ressources non gérées maintenant , avant que l'instance de classe ne soit hors de portée et que Finalize soit appelé. Ceci est important pour des raisons qui devraient être évidentes - une ressource non gérée peut avoir des dépendances sur d'autres ressources non gérées, et si elles sont éliminées (ou finalisées) dans le mauvais ordre, de mauvaises choses peuvent se produire.
Donc, si la classe instanciée dans le bloc using utilise des ressources non gérées, alors la réponse est oui - c'est approprié.
Notez que IDisposable n'est pas prescriptif car il est uniquement destiné à libérer des ressources non gérées - juste que c'est son objectif principal . Il se peut que l'auteur de la classe ait une action qu'il souhaite appliquer à un certain moment, et l'implémentation d'IDisposable peut être un moyen d'y arriver, mais que ce soit ou non une solution élégante est quelque chose qui peut recevoir une réponse au cas par cas.
Quoi qu'il en soit, l'utilisation de "using" implique que la classe implémente IDisposable, de sorte qu'elle ne viole pas l'expressivité du code; cela montre clairement ce qui se passe, en fait.
la source
L'utilisation de
using
implique la présence d'uneDispose()
méthode. D'autres programmeurs supposeront qu'une telle méthode existe sur l'objet. Par conséquent, si un objet n'est pas jetable, vous ne devez pas l'utiliserusing
dessus.La clarté du code est primordiale. Soit omettez le
using
, soit implémentezIDisposable
sur l'objet.MiniProfiler semble utiliser
using
comme mécanisme pour «clôturer» le code profilé. Il y a un certain mérite à cela; vraisemblablement, MiniProfiler appelle soitDispose()
pour arrêter un minuteur, soit le minuteur est arrêté lorsque l'objet MiniProfiler sort de la portée.Plus généralement, vous invoquerez
using
lorsqu'une sorte de finalisation doit se produire automatiquement. La documentation dehtml.BeginForm
indique que, lorsque la méthode est utilisée dans uneusing
instruction, elle restitue la</form>
balise de fermeture à la fin duusing
bloc.Cela ne signifie pas nécessairement que ce n'est toujours pas un abus.
la source
IDisposable
/Dispose()
bien qu'il n'ait rien à disposer dans le sens décrit par OP?Dispose
est nécessaire pourusing
avoir du sens du tout (indépendamment du fait que ce soit approprié). Les exemples de PO implémentent tousDispose
, n'est-ce pas? Et IIUC, la question est de savoir s'il est correct que ces classes utilisentDispose
, plutôt qu'une autre méthode (commeStop()
pour MiniProfiler).using
est sûr d'erreur et d'exception. Il garantit queDispose()
sera appelé indépendamment de toute erreur du programmeur. Il n'interfère pas avec la capture ou la gestion des exceptions, mais laDispose()
méthode est exécutée récursivement dans la pile lorsqu'une exception est levée.Objets qui implémentent
IDispose
mais n'ont rien à disposer lorsqu'ils sont terminés. Sont au mieux, à l'épreuve du temps leur conception. Pour que vous n'ayez pas à refactoriser votre code source, alors qu'à l'avenir, ils doivent alors disposer de quelque chose.la source