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

FileFont 是访问非托管资源(本例中为文件句柄和设备上下文)的托管类型的示例。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 而不是 IDisposableusing 语句将调用 DisposeAsyncawaits 返回的 ValueTaskIf 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 语句可确保调用 DisposeDisposeAsync,即使 using 块中发生异常也是如此。The using statement ensures that Dispose (or DisposeAsync) is called even if an exception occurs within the using block. 通过将对象放入 try 块中,然后调用 finally 块中的 Dispose(或 DisposeAsync),可以实现相同的结果;实际上,这就是编译器转换 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

有关详细信息,请参阅 C# 语言规范中的 using 语句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