¿Cuándo debería usar bloques “usando” en C #?

¿Existen casos particulares en los que debería (o no debería) utilizar bloques “que usan”?

using(SomeType t = new SomeType()){ ... } 

Cuando la clase IDisposable implementa IDisposable .

Algunos objetos necesitan que se tomen medidas cuando hayas terminado con ellos. Por lo general, esto se debe a que el objeto utiliza algún tipo de recurso que debe eliminarse. Por ejemplo, si tiene un objeto de archivo de clase File y este objeto abre un archivo desde el sistema de archivos, el archivo en el sistema de archivos deberá cerrarse nuevamente.

Si acaba de abandonar el objeto de archivo, y se olvidó de llamar a file.Close () no se limpiaría hasta que se ejecutara el Garbage Collector (GC) y resolvió que todavía no se estaba utilizando el objeto de archivo. Cuando se ejecute Garbage Collector, debe dejarse en Common Language Runtime (CLR) para decidir. Si el GC no se ejecuta durante bastante tiempo después de haber terminado con el archivo, el archivo podría permanecer abierto durante mucho tiempo. Esto puede suponer un gran problema si hay muchos objetos de archivo, o si algo quiere abrir un archivo, pero no puede porque el objeto de archivo que dejó todavía está dando vueltas.

Para resolver este problema, C # tiene la interfaz IDisposable. Esto tiene un método llamado Dispose. Las clases que requieren cierta limpieza implementan este método de eliminación. Esto le proporciona una forma estándar de limpiar cualquier objeto que use recursos. Hay muchas clases que necesitan tener un Dispose llamado. El problema con esto es que el código se cubre con llamadas a Dispose, y son difíciles de seguir porque el lugar donde se actualizó el objeto y se llama a Dispose para limpiarlo son diferentes. Por lo tanto, tenía que mirar mucho el código y tener mucho cuidado de comprobar si había llamadas para desechar en el lugar correcto.

Para resolver este problema, C # introdujo la palabra clave ‘usar’. Puede colocar una palabra clave ‘using’ en el lugar donde desea crear un objeto, y esto garantiza que se invocará Dispose en su lugar. Garantiza que se llamará a Dispose pase lo que pase … incluso si hay una excepción lanzada dentro del cuerpo de la instrucción using.

Por lo tanto, debe usar ‘usar’ cuando desee asegurarse de que un objeto que asigna recursos se limpiará.


using solo se puede usar para objetos que están declarados en la stack, es decir, en una función. No funciona para objetos que están declarados como miembros de una clase. Para ellos, debes llamar a ti mismo. Puede que tenga que implementar Eliminar en su clase para que pueda invocar Eliminar en cualquier objeto miembro que lo requiera.


Los objetos comunes que necesitan usar invocados son: archivos, conexiones de bases de datos, objetos gráficos como pluma y pincel.


Algunas veces también se usa cuando quieres que dos operaciones sucedan juntas. Por ejemplo, si desea escribir una statement de registro cuando se ingresa un bloque de código y cuando sale puede escribir una clase de registro que pueda usar así:

 using( Log log = new Log("Doing stuff") ) { // Stuff } 

El constructor de la clase de registro podría escribir el mensaje y el método Dispose también podría escribirlo. Implemente el finalizador (~ Log) para afirmar si el método Dispose no se llama para asegurarse de que el ‘uso’ se recuerde alrededor del ‘nuevo Log’.

Use siempre que el tipo implemente IDisposable , a menos que vaya a envolverlo en un bloque try / catch todas formas, entonces también podría (dependiendo de qué aspecto prefiera) usar un bloque finally .

Veo muchas otras respuestas indicadas cuando debería tener una statement de using . Quiero abordar cuándo específicamente no debería tener una statement de using :

Si necesita usar su objeto fuera del scope de la función actual, no tenga un bloque de using . Un buen ejemplo es un método de fábrica que devuelve una conexión de base de datos o un método que debe devolver un lector de datos. En cualquiera de esos casos, si crea su objeto con una instrucción using , se eliminará antes de que se devuelva el método y, por lo tanto, no se podrá usar fuera del método.

Ahora, aún desea asegurarse de que esos objetos estén dispuestos, por lo que aún podría querer using una statement en alguna parte. Simplemente no lo incluya en el método donde se crea realmente el objeto. En cambio, puede envolver la llamada a la función en sí misma en una instrucción de using .

Cuando SomeType implementa IDisposable.

Esa es una pista para usted, el desarrollador, de que SomeType utiliza recursos no administrados que deben ser limpiados.

Ejemplo:

  using(SqlConnection MyConnection = new SqlConnection("Connection string")) { MyConnection.Open(); //... // 1. SQLConnection is a type that implements IDisposable // 2. So you can use MyConnection in a using statement // 3. When using block finishes, it calls Dispose method of // SqlConnection class // 4. In this case, it will probably close the connection to // the database and dispose MyConnection object } 

Puede crear sus propios objetos que implemente IDisposable:

 public class MyOwnObjectThatImplementsIDisposable : IDisposable { //... some code public void Dispose() { // Put here the code you want to be executed when the // using statement finish. } } 

Por lo tanto, podría usar un objeto de tipo MyOwnObjectThanImplementsIDisposable en una statement using:

  using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable) { // When the statement finishes, it calls the // code you´ve writed in Dispose method // of MyOwnObjectThatImplementsIDisposable class } 

Espero que esto ayude

En este contexto, la instrucción using es útil para los tipos que implementan IDisposable. Cuando el bloque de código sale del scope de la instrucción using , se llama implícitamente a Dispose() . Es un buen hábito cuando trabaja con objetos que desea desechar inmediatamente después del uso.

Una instancia específica en la que debe tener cuidado al usar un bloque de using es con un WCF Service Client .

Como se señala en este artículo de MSDN , envolver un cliente WCF (que implementa IDisposable ) en un bloque de using podría enmascarar cualquier error que provoque que el cliente quede en estado de error (como un tiempo de espera o un problema de comunicación). En pocas palabras, cuando se llama a Dispose() se dispara el método Close() del cliente, pero se lanza y se produce un error porque está en estado de falla. La excepción original queda enmascarada por la segunda excepción. No está bien.

Hay varias soluciones alternativas, incluida una en el artículo de MSDN. Otros se pueden encontrar en IServiceOriented y blog.davidbarret.net .

Yo prefiero el último método, yo mismo.

Si quieres una regla de resumen Cada vez que un objeto usando IDisposable donde no tendría una captura, use usando. El uso, esencialmente, es este patrón:

 try { //instantiate and use object } finally { //dispose object } 

Si no necesita una captura, usar puede ahorrarle tipeo, lo cual es algo bueno.

La regla primaria es: * Utilice la instrucción USING cuando los objetos implementen una interfaz IDisposable.

Esta interfaz proporciona el método Dispose, que debería liberar los recursos del objeto. Si no se invoca este método, el objeto permanecerá en la memoria siempre que CLR quiera realizar la recolección de basura. Si el progtwigdor usa la instrucción USING, al final se eliminará el objeto y todos los recursos serán gratuitos.

Es muy importante que todos los recursos que ya no se utilizan sean gratuitos lo antes posible.

Para obtener más información al respecto, visite este enlace: microsoft

Quizás vale la pena mencionar que la razón subyacente para agregar “usar” lo C # languge es la siguiente: algunos recursos pueden ser lo suficientemente escasos como para que no tenga sentido esperar a que GC llame a IDisposable. Por ejemplo, conexiones de DB. Si usas try / catch / finally, no terminarás con una conexión colgante, pero la conexión se mantendrá suspendida hasta que GC no entre y esto puede demorar un tiempo (si no la cierras explícitamente). SI usa “usar” (disculpe el juego de palabras) liberará la conexión inmediatamente, incluso si olvidó cerrarla e incluso si se produjo alguna excepción dentro del bloque de uso.
Otra razón, como menciona el post anterior, es que los progtwigdores no siempre usan finalmente para limpiar. Si no se usa finalmente en el caso de una excepción, se terminan con recursos que pierden …

Una situación es cuando desea hacer algo al comienzo de un bloque de código, y luego deshacerlo al final del bloque, incondicionalmente (incluso si hay un lanzamiento).

El ctor para la clase desechable que usted construye (y llama dentro del uso) realizaría la acción, y luego el método Dispose desharía esa acción. Por lo general, así es como lo uso.

Otras personas ya han mencionado sobre “IDisposable”.

Pero una de las advertencias al usar la statement de “uso” es que, cualquier excepción arrojada dentro de “usar” no será capturada, incluso si se piensa que “SomeType” será eliminado independientemente.

Entonces en el siguiente fragmento,

 using (SomeType t = new SomeType()){ throw new Exception("thrown within using"); } 

throw new Exception("thrown within using"); no debe ser ignorado.

También agregaría que use una instrucción using() si algo implementa IDispose y también si ese algo del que quiere deshacerse guarda en recursos NO GESTIONADOS como conexiones de bases de datos y manejadores de archivos.

Si se trata de un objeto normal con una List , donde T es como un objeto Customer que contiene nombres y direcciones, entonces no es necesario. El recolector de basura es lo suficientemente inteligente como para administrar esto por ti. Pero el recolector de basura NO devolverá las conexiones al grupo de conexiones ni cerrará los identificadores de archivos.