IDE0063什么时候配置?

When does IDE0063 dispose?

我正在尝试了解此 C# 8 简化功能:

IDE0063 'using' statement can be simplified

比如我有:

void Method()
{
    using (var client = new Client())
    {
        // pre code...
        client.Do();
        // post code...
    } --> client.Dispose() was called here.
    // more code...
}

IDE 告诉我可以通过这样写来简化这个 using 语句:

void Method()
{
    using (var client = new Client());
    // pre code...
    client.Do();
    // post code...
    // more code...
}

我无法理解它是如何工作的以及它如何决定我不再是 using 变量。更具体地说,它到底什么时候调用 client.Dispose 方法?

您使用的是 C# 8。在旧的 C# 版本中,; 会使此无效。

在新语法中,client 保留在周围方法(或其他 {} 范围块)的范围内。请注意,您也可以省略 () 的外部对。

它被称为using 声明,文档是here

void Method()
{
    using var client = new Client();
    // pre code...
    client.Do();
    // post code...
    // more code...
} --> client.Dispose() is called here (at the latest)

从逻辑上讲,Dispose 发生在 },但优化器可能会更早执行。

编辑

我注意到 // more codeusing 块结束后,阻止了这种改进的出现。所以转换成下面的代码就不会再有歧义了:

void Method()
{
    // not relevant code

    using (var client = new Client())
    {
        // pre code...
        client.Do();
        // post code...
    }
}

进入此代码:

void Method()
{
    // not relevant code

    using var client = new Client();
    // pre code...
    client.Do();
    // post code...
}

简短的回答是新的(可选的)using 语句语法继承了它的 父级 作用域。

我不得不同意 OP 的观点,这是 C# 8.0 中一个非常令人困惑的变化,原因有很多。

从历史上看,using 一直与其他块(ifswitch 等)一样使用作用域。和 if 一样,using 语句的范围是下一行 或代码块

所以这样写是完全有效的:

using (var client = new Client())
    client.Do();

这意味着 client 仅在单个语句的范围内,这非常适合单行操作,例如触发没有 return 值的 SQL 存储过程。

但现在我们还有:

using var client = new Client();
client.Do();

这根本不是一回事; client 仍然在整个方法的范围内。

现在,Visual Studio 只会在您原来的 using 块之后没有任何内容的情况下建议进行此更改,因此它在功能上是相同的。但是,如果以后添加更多代码怎么办?使用旧的范围符号,新代码是在范围内还是在范围外就非常清楚了。使用新语法,using 之后的所有内容都在范围内,但可能不清楚。

Roslyn 团队可能认为这并不重要。与流控制语句(if 等)不同,您真的关心您的对象是否在多行代码的范围内吗?可能不会。但就像所有事情一样,这取决于情况。

在某些方面,这是一个改进,因为它清楚地表明,"Instantiate this object and call Dispose() when it goes out of scope." 对象在超出范围(即方法结束)时总是被销毁并被垃圾收集,但这确实 不是 表示 Dispose() 被调用。将 using 添加到局部变量声明只是实现这一目标的一种方式。

最后,这是 big,如果您的目标是 .NET Framework,您可能并没有真正使用 C# 8.0。

你可能认为你是;我做到了。您可能 运行 Visual Studio 2019 16.3+。您甚至可能安装了最新版本的 Microsoft.Net.Compilers 软件包,并且 表示 您正在获取 C# 8.0,对吗?但你不是。默认情况下,.NET Framework 的上限为 C# 7.3。

在我的测试中,当我以 .NET 4.8 为目标时,Visual Studio 很聪明,不会提供 C# 8.0 建议。但是,如果我以旧版本 (4.7.2) 为目标,我 do 会收到此建议,然后生成构建错误。 IDE 不会向您显示该错误 - 您的项目看起来很干净 - 但您在实际构建时会遇到两个语法错误。

针对 .NET 4.8 时,如果您尝试使用 C# 8.0 语法,您将获得友好的

CS8370 C# Feature is not available in C# 7.3. Please use language version 8.0 or greater.

以及将 <LangVersion>8.0</LangVersion> 添加到您的项目文件的提议(即使 Microsoft 官方不支持)。它有效,但有警告。但对于较旧的 .NET 版本,情况似乎并非如此。因此,在旧项目上接受这些新语法提示时要格外小心!

更新: 我错了触发提示的旧 NET Framework 版本。罪魁祸首是 Microsoft.Net.Compilers 的旧版本 (2.10.0)。那是与旧版本 Visual Studio 兼容的最后一个版本。删除该软件包后,不再提供提示。