En C #, la using
declaración se utiliza para disponer de manera determinista los recursos sin esperar al recolector de basura. Por ejemplo, se puede usar para:
Deseche comandos SQL o conexiones,
Cerrar transmisiones, liberando la fuente subyacente como un archivo,
Elementos GDI + gratuitos,
etc.
Noté que using
se usa cada vez más en casos donde no hay nada que desechar, pero donde es más conveniente para la persona que llama escribir un using
bloque en lugar de dos comandos separados.
Ejemplos:
MiniProfiler , escrito por el equipo de Stack Overflow, usa
using
para denotar bloques para perfilar:using (profiler.Step("Name goes here")) { this.DoSomethingUseful(i - 1); }
Un enfoque alternativo sería tener dos bloques:
var p = profiler.Start("Name goes here"); this.DoSomethingUseful(i - 1); profiler.Stop(p);
Otro enfoque sería utilizar acciones:
profiler.Step("Name goes here", () => this.DoSomethingUseful(i - 1));
ASP.NET MVC también elegido
using
para formularios:<% using (Html.BeginForm()) { %> <label for="firstName">Name:</label> <%= Html.TextBox("name")%> <input type="submit" value="Save" /> <% } %>
¿Es apropiado ese uso? Cómo justificarlo, dado que hay varios inconvenientes:
Los principiantes se perderían, ya que dicho uso no se corresponde con el que se explica en los libros y las especificaciones del idioma,
El código debe ser expresivo. Aquí, la expresividad sufre, ya que el uso apropiado de
using
es mostrar que detrás hay un recurso, como una secuencia, una conexión de red o una base de datos que debe liberarse sin esperar al recolector de basura.
fuente
using
:profiler.Stop(p)
No se garantiza que la última declaración (por ejemplo ) se ejecute ante las excepciones y el flujo de control.Respuestas:
Su última afirmación: que "el uso apropiado del uso es mostrar que detrás hay un recurso, como un flujo, una conexión de red o una base de datos que debería liberarse sin esperar al recolector de basura" es incorrecto, y la razón es en la documentación de la interfaz IDisposable: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
Por lo tanto, si su clase utiliza recursos no administrados, no importa cuándo quiera o no que ocurra GC: no tiene nada que ver con GC ya que los recursos no administrados no son GC'ed ( https: // stackoverflow. com / questiones / 3607213 / what-is-mean-by-managed-vs-unmanaged-resources-in-net ).
Entonces, el propósito de "usar" no es evitar esperar en GC, es forzar una liberación de esos recursos no administrados ahora , antes de que la instancia de clase salga del alcance y se llame Finalizar. Esto es importante por razones que deberían ser obvias: un recurso no administrado puede depender de otros recursos no administrados, y si se eliminan (o finalizan) en el orden incorrecto, pueden suceder cosas malas.
Entonces, si la clase que se instancia en el bloque de uso usa recursos no administrados, entonces la respuesta es sí, es apropiado.
Sin embargo, tenga en cuenta que IDisposable no es prescriptivo sobre si es solo para liberar recursos no administrados, solo que este es su propósito principal . Se puede darse el caso de que el autor de la clase tiene algún tipo de acción que ellos quieren hacer cumplir sucediendo en un momento determinado, y la aplicación de IDisposable puede ser una manera de conseguir que esto suceda, pero si eso es una solución elegante es algo que puede solo se responderá caso por caso.
Cualquiera que sea, el uso de "usar" implica que la clase implementa IDisposable, por lo que no viola la expresividad del código; De hecho, deja bastante claro lo que está sucediendo.
fuente
El uso de
using
implica la presencia de unDispose()
método. Otros programadores supondrán que dicho método existe en el objeto. En consecuencia, si un objeto no es desechable, no debe usarlousing
.La claridad del código es el rey. Omita
using
o implementeIDisposable
en el objeto.MiniProfiler parece estar utilizando
using
como mecanismo para "cercar" el código que se perfila. Hay algo de mérito en esto; presumiblemente, MiniProfiler está llamandoDispose()
para detener un temporizador o el temporizador se detiene cuando el objeto MiniProfiler sale del alcance.En términos más generales, invocaría
using
cuando algún tipo de finalización deba ocurrir automáticamente. La documentación para loshtml.BeginForm
estados que, cuando el método se utiliza en unausing
declaración, representa la</form>
etiqueta de cierre al final delusing
bloque.Eso no significa necesariamente que todavía no sea abuso.
fuente
IDisposable
/ aDispose()
pesar de no tener nada que desechar en el sentido que OP describe?Dispose
es necesario parausing
que tenga sentido (independientemente de si es apropiado). Todos los ejemplos de OP implementanDispose
, ¿no? Y IIUC, la pregunta es si es correcto que estas clases usenDispose
, en lugar de algún otro método (comoStop()
MiniProfiler).using
Es seguro el error y la excepción. AseguraDispose()
que se llamará independientemente de cualquier error que cometa el programador. No interfiere con la captura o el manejo de excepciones, pero elDispose()
método se ejecuta recursivamente en la pila cuando se produce una excepción.Objetos que se implementan
IDispose
pero que no tienen nada que desechar cuando se hacen. En el mejor de los casos, a prueba de futuro de su diseño. Para que no tenga que refactorizar su código fuente, cuando en el futuro, ellos tengan que deshacerse de algo.fuente