using 语句(C# 参考)

提供可确保正确使用 IDisposable 对象的方便语法。 从 C#8.0 开始,using 语句可确保正确使用 IAsyncDisposable 对象。

示例

下面的示例演示如何使用 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);
}

从 C# 8.0 开始,可以对不需要使用大括号的 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);

备注

FileFont 是访问非托管资源(本例中为文件句柄和设备上下文)的托管类型的示例。 有许多其他类别的非托管资源和封装这些资源的类库类型。 所有此类类型都必须实现 IDisposable 接口或 IAsyncDisposable 接口。

IDisposable 对象的生存期限于单个方法时,应在 using 语句中声明并实例化它。 using 语句按照正确的方式调用对象上的 Dispose 方法,并(在按照前面所示方式使用它时)会导致在调用 Dispose 时对象自身处于范围之外。 在 using 块中,对象是只读的并且无法进行修改或重新分配。 如果对象实现 IAsyncDisposable 而不是 IDisposableusing 语句将调用 DisposeAsyncawaits 返回的 ValueTask。 有关 IAsyncDisposable 的详细信息,请参阅实现 DisposeAsync 方法

using 语句可确保调用 DisposeDisposeAsync,即使 using 块中发生异常也是如此。 通过将对象放入 try 块中,然后调用 finally 块中的 Dispose(或 DisposeAsync),可以实现相同的结果;实际上,这就是编译器转换 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);
    try
    {
        string? item;
        do
        {
            item = reader.ReadLine();
            Console.WriteLine(item);
        } while (item != null);
    }
    finally
    {
        reader?.Dispose();
    }
}

较新的 using 语句语法转换为类似的代码。 try 块在声明变量的位置打开。 finally 块添加在封闭块的末尾,通常是在方法的末尾。

有关 try-finally 语句的详细信息,请参阅 try-finally 一文。

可在单个 using 语句中声明一个类型的多个实例,如下面的示例中所示。 注意,在单个语句中声明多个变量时,不能使用隐式类型的变量 (var):

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 一起引入的新语法,合并同一类型的多个声明,如下面的示例中所示:

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 语句,但这不是最佳做法。 在这种情况下,控件退出 using 块以后,对象保留在作用域中,但是可能没有访问其未托管资源的权限。 换而言之,它不再是完全初始化的。 如果尝试在 using 块外部使用该对象,则可能导致引发异常。 因此,最好在 using 语句中实例化该对象并将其范围限制在 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

有关释放 IDisposable 对象的详细信息,请参阅使用实现 IDisposable 的对象

C# 语言规范

有关详细信息,请参阅 C# 语言规范中的 using 语句。 该语言规范是 C# 语法和用法的权威资料。

请参阅