Оператор using (справочник по C#)using statement (C# Reference)

Предоставляет удобный синтаксис, обеспечивающий правильное использование объектов IDisposable.Provides a convenient syntax that ensures the correct use of IDisposable objects. Начиная с C# 8.0 инструкция using гарантирует правильное использование объектов IAsyncDisposable.Beginning in C# 8.0, the using statement ensures the correct use of IAsyncDisposable objects.

ПримерExample

В следующем примере показано использование оператора using.The following example shows how to use the using statement.

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

Начиная с версии C# 8.0, можно использовать следующий альтернативный синтаксис для оператора using без использования фигурных скобок:Beginning with C# 8.0, you can use the following alternative syntax for the using statement that doesn't require braces:

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

ПримечанияRemarks

File и Font представляют собой примеры управляемых типов, которые обращаются к неуправляемым ресурсам (в данном случае это обработчики файлов и контексты устройств).File and Font are examples of managed types that access unmanaged resources (in this case file handles and device contexts). Существуют и многие другие виды неуправляемых ресурсов и типов библиотек классов, которые их инкапсулируют.There are many other kinds of unmanaged resources and class library types that encapsulate them. Все эти типы должны реализовывать интерфейс IDisposable или интерфейс IAsyncDisposable.All such types must implement the IDisposable interface, or the IAsyncDisposable interface.

Когда время существования объекта IDisposable ограничено одним методом, необходимо объявить его и создать его экземпляр в операторе using.When the lifetime of an IDisposable object is limited to a single method, you should declare and instantiate it in the using statement. Оператор using правильно вызывает метод Dispose для объектов, а также (если он используется, как показано выше) становится причиной выхода объекта из области действия, как только вызывается метод Dispose.The using statement calls the Dispose method on the object in the correct way, and (when you use it as shown earlier) it also causes the object itself to go out of scope as soon as Dispose is called. В блоке using объект доступен только для чтения, и изменить или переназначить его невозможно.Within the using block, the object is read-only and can't be modified or reassigned. Если объект реализует IAsyncDisposable вместо IDisposable, то инструкция using вызывает DisposeAsync и awaits, возвращенный ValueTask.If the object implements IAsyncDisposable instead of IDisposable, the using statement calls the DisposeAsync and awaits the returned ValueTask. Дополнительные сведения о IAsyncDisposable см. в статье Реализация метода DisposeAsync.For more information on IAsyncDisposable, see Implement a DisposeAsync method.

Использование инструкции using обеспечивает вызов Dispose (или DisposeAsync), даже если в блоке using возникает исключение.The using statement ensures that Dispose (or DisposeAsync) is called even if an exception occurs within the using block. Тот же результат можно получить, поместив объект в блок try, а затем вызвав Dispose (или DisposeAsync) в блоке finally; фактически компилятор переводит инструкцию using именно так.You can achieve the same result by putting the object inside a try block and then calling Dispose (or DisposeAsync) in a finally block; in fact, this is how the using statement is translated by the compiler. Во время компиляции представленный выше код разворачивается в следующий (обратите внимание на дополнительные фигурные скобки, создающие ограниченную область действия для объекта):The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):

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

Новый синтаксис инструкции using преобразуется в похожий код.The newer using statement syntax translates to similar code. Блок try открывается там, где объявлена переменная.The try block opens where the variable is declared. Блок finally добавляется в конец охватывающего блока, как правило, в конце метода.The finally block is added at the close of the enclosing block, typically at the end of a method.

Дополнительные сведения об инструкции try-finally см. в описании try-finally.For more information about the try-finally statement, see the try-finally article.

В одной инструкции using можно объявить сразу несколько экземпляров типа, как показано в следующем примере.Multiple instances of a type can be declared in a single using statement, as shown in the following example. Обратите внимание, что невозможно использовать неявно типизированные переменные (var) при объявлении нескольких переменных в одной инструкции:Notice that you can't use implicitly typed variables (var) when you declare multiple variables in a single statement:

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

Несколько объявлений одного типа можно объединить с помощью нового синтаксиса, представленного в C# 8, как показано в следующем примере:You can combine multiple declarations of the same type using the new syntax introduced with C# 8 as well, as shown in the following example:

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

Вы можете создать экземпляр объекта ресурсов, а затем передать переменную в инструкцию using, однако делать это не рекомендуется.You can instantiate the resource object and then pass the variable to the using statement, but this isn't a best practice. В этом случае объект остается в области действия и после того, как блок using теряет контроль, хотя доступа к неуправляемым ресурсам у него, скорее всего, не будет.In this case, after control leaves the using block, the object remains in scope but probably has no access to its unmanaged resources. Иными словами, он уже не полностью инициализируется.In other words, it's not fully initialized anymore. При попытке использовать объект за пределами блока using может возникнуть исключение.If you try to use the object outside the using block, you risk causing an exception to be thrown. По этой причине лучше создать экземпляр объекта в инструкции using и ограничить область действия блоком using.For this reason, it's better to instantiate the object in the using statement and limit its scope to the using block.

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

Дополнительные сведения об утилизации объектов IDisposable см. в разделе Использование объектов, реализующих IDisposable.For more information about disposing of IDisposable objects, see Using objects that implement IDisposable.

Спецификация языка C#C# language specification

Дополнительные сведения см. в разделе Оператор using в статье Спецификации языка C#.For more information, see The using statement in the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee also