using 语句(C# 参考)

using 语句提供可确保正确使用 IDisposable 对象的方便语法。 await using 语句可确保正确使用 IAsyncDisposable 对象。 语言支持实现 System.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);
}

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 声明中声明并实例化它。 using 声明以正确方式在对象上调用 Dispose 方法,当它超出范围时。 当 Dispose 调用时,using 语句导致对象本身超出范围。 在 using 块中,对象是只读的并且无法进行修改或重新分配。 使用 using 声明声明的变量是只读的。 如果对象实现 IAsyncDisposable 而不是 IDisposable,任一 using 窗体将调用 DisposeAsyncawaits 返回的 ValueTask。 有关 IAsyncDisposable 的详细信息,请参阅IAsyncDisposable

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

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

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

可在单个 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);
}

也可以使用声明语法,合并同一类型的多个声明,如下面的示例中所示:

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# 语法和用法的权威资料。

请参阅