using (Instrucción, Referencia de C#)

Ofrece una sintaxis adecuada que garantiza el uso correcto de objetos IDisposable. A partir de C# 8.0, la instrucción using garantiza el uso correcto de los objetos IAsyncDisposable.

Ejemplo

En el ejemplo siguiente se muestra cómo usar la instrucción using.

string manyLines=@"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";

using (var reader = new StringReader(manyLines))
{
    string? item;
    do {
        item = reader.ReadLine();
        Console.WriteLine(item);
    } while(item != null);
}

A partir de C# 8.0, puede usar la siguiente sintaxis alternativa para la instrucción using que no requiere llaves:

string manyLines=@"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";

using var reader = new StringReader(manyLines);
string? item;
do {
    item = reader.ReadLine();
    Console.WriteLine(item);
} while(item != null);

Comentarios

File y Font son ejemplos de tipos administrados que acceden a recursos no administrados (en este caso, identificadores de archivo y contextos de dispositivo). Hay muchos otros tipos de recursos no administrados y tipos de la biblioteca de clases que los encapsulan. Todos estos tipos deben implementar la interfaz IDisposable o la interfaz IAsyncDisposable.

Cuando la duración de un objeto IDisposable se limita a un único método, debe declarar y crear instancias del mismo en la instrucción using. La instrucción using llama al método Dispose del objeto de forma correcta y (cuando se usa tal y como se muestra anteriormente) también hace que el propio objeto salga del ámbito en cuanto se llame a Dispose. Dentro del bloque using, el objeto es de solo lectura y no se puede modificar ni reasignar. Si el objeto implementa IAsyncDisposable en lugar de IDisposable, la instrucción using llama al objeto DisposeAsync y awaits al objeto ValueTask devuelto. Para obtener más información sobre IAsyncDisposable, vea Implementación de un método DisposeAsync.

La instrucción using asegura que se llama al método Dispose (o DisposeAsync) aunque se produzca una excepción en el bloque using. Puede obtener el mismo resultado si coloca el objeto dentro de un bloque try y llama a Dispose (o DisposeAsync) en un bloque finally; de hecho, es así como el compilador traduce la instrucción using. El ejemplo de código anterior se extiende al siguiente código en tiempo de compilación (tenga en cuenta las llaves adicionales para crear el ámbito limitado del objeto):

string manyLines=@"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";

{
    var reader = new StringReader(manyLines);
    try {
        string? item;
        do {
            item = reader.ReadLine();
            Console.WriteLine(item);
        } while(item != null);
    } finally
    {
        reader?.Dispose();
    }
}

La nueva sintaxis de la instrucción using se traduce en un código similar. Se abre el bloque try en el que se declara la variable. El bloque finally se agrega al cierre del bloque de inclusión, normalmente, al final de un método.

Consulte el artículo sobre try-finally para obtener más información sobre la instrucción try-finally.

Se pueden declarar varias instancias de un tipo en una sola instrucción using, tal y como se muestra en el ejemplo siguiente. Tenga en cuenta que no se pueden usar variables con tipo implícito (var) cuando se declaran varias variables en una sola instrucción:

string numbers=@"One
Two
Three
Four.";
string letters=@"A
B
C
D.";

using (StringReader left = new StringReader(numbers),
    right = new StringReader(letters))
{
    string? item;
    do {
        item = left.ReadLine();
        Console.Write(item);
        Console.Write("    ");
        item = right.ReadLine();
        Console.WriteLine(item);
    } while(item != null);
}

También puede combinar varias declaraciones del mismo tipo con la nueva sintaxis introducida con C# 8, tal y como se muestra en el ejemplo siguiente:

string numbers=@"One
Two
Three
Four.";
string letters=@"A
B
C
D.";

using StringReader left = new StringReader(numbers),
    right = new StringReader(letters);
string? item;
do {
    item = left.ReadLine();
    Console.Write(item);
    Console.Write("    ");
    item = right.ReadLine();
    Console.WriteLine(item);
} while(item != null);

Puede crear una instancia del objeto de recurso y luego pasar la variable a la instrucción using, pero esto no es un procedimiento recomendado. En este caso, después de que el control abandone el bloque using el objeto permanece en el ámbito, pero probablemente ya no tenga acceso a sus recursos no administrados. En otras palabras, ya no se inicializa totalmente. Si intenta usar el objeto fuera del bloque using, corre el riesgo de iniciar una excepción. Por este motivo, es mejor crear una instancia del objeto en la instrucción using y limitar su ámbito al bloque using.

string manyLines=@"This is line one
This is line two
Here is line three
The penultimate line is line four
This is the final, fifth line.";

var reader = new StringReader(manyLines);
using (reader)
{
    string? item;
    do {
        item = reader.ReadLine();
        Console.WriteLine(item);
    } while(item != null);
}
// reader is in scope here, but has been disposed

Para obtener más información sobre cómo eliminar objetos IDisposable, vea Uso de objetos que implementan IDisposable.

Especificación del lenguaje C#

Para obtener más información, vea el apartado Instrucción using en la Especificación del lenguaje C#. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.

Vea también