using (Instrucción, Referencia de C#)

La using instrucción proporciona una sintaxis cómoda que garantiza el uso correcto de IDisposable objetos. La await using instrucción garantiza el uso correcto de IAsyncDisposable objetos. El lenguaje admite tipos descartables asincrónicos que implementan la System.IAsyncDisposable interfaz .

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);
}

La declaración using 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 de él en la instrucción using o en la declaración using. La declaración using llama al método Dispose en el objeto de la manera correcta cuando sale del ámbito. La instrucción using hace que el propio objeto salga del ámbito en cuando se llama a Dispose. Dentro del bloque using, el objeto es de solo lectura y no se puede modificar ni reasignar. Una variable declarada con una declaración using es de solo lectura. Si el objeto implementa IAsyncDisposable en lugar de IDisposable, una de las formas using llama a DisposeAsync y usa awaits con el valor de ValueTask devuelto. Para obtener más información sobre IAsyncDisposable, vea Implementación de un método DisposeAsync.

Ambas formas using garantizan que se llama a 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 y la declaració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 mediante la sintaxis de declaración, 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