IDE0063何时处置?

我试图理解 C # 8的这个简化特性:

IDE0063的‘ using’语句可以简化

例如,我有:

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方法?

15051 次浏览

你正在使用 C # 8。在旧的 C # 版本中,;会使这个无效。

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

它叫做 使用声明,文档是 给你

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

从逻辑上讲,Dispose 发生在 },但优化器可能会提前这样做。

剪辑

我注意到在 using块结束后使用 // more code可以防止出现这种改进。因此,如果您转换以下代码,就不会有更多的模糊性:

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只在单个语句的范围内,这对于单行操作非常有用,比如触发一个没有返回值的 SQL 存储过程。

但现在我们还有:

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

这根本不是一回事; 对于整个方法,client仍然在作用域内。

现在,VisualStudio 只会在原来的 using代码块之后没有任何更改时才建议进行此更改,因此它的功能是相同的。但是如果以后添加更多的代码会怎么样呢?使用旧的作用域表示法,可以很清楚地看到新代码是在作用域内还是在作用域外。使用新的语法,using之后的所有内容都在作用域中,但这可能并不清楚。

罗斯林团队可能已经认识到这并不重要。与流控制语句(if等)不同,您是否真正关心对象是否在作用域中多存在几行代码?也许不会。但是像所有事情一样,这要看情况。

在某些方面,这是一个改进,因为它清楚地说,“实例化这个对象 当它超出范围时调用 Dispose()。”当对象超出作用域(即方法结束)时,总是会销毁它们并收集垃圾,但是 没有意味着调用 Dispose()。将 using添加到局部变量声明中只是实现这一点的一种方法。

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

你可能觉得你是,我就是。您可能正在运行 Visual Studio 201916.3 + 。您甚至可能已经安装了 Microsoft.Net.Compilers软件包的最新版本,并且您将获得 C # 8.0版本的 ,对吗?但你不是。默认情况下。NET Framework 的上限是 C # 7.3。

在我的测试中,当我瞄准。NET 4.8,Visual Studio 很聪明,不会提供 C # 8.0的建议。但是,如果我的目标是一个较老的版本(4.7.2) ,我 得到这个建议,然后生成一个构建错误。IDE 不会显示这个错误-您的项目看起来很干净-但是实际构建时会出现两个语法错误。

当目标是.NET 4.8时,如果你尝试使用 C # 8.0语法,你会得到友好的

CS8370 C # Feature 在 C # 7.3中不可用。请使用语言版本8.0或更高版本。

以及向您的项目文件添加 <LangVersion>8.0</LangVersion>的提议(尽管微软官方不支持这种做法)。它的工作,与警告。但是年纪大了。NET 版本似乎并非如此。因此,在接受旧项目上的这些新语法提示时要格外小心!

更新: 我错误地认为旧版本的 NET Framework 会触发提示。罪魁祸首是 Microsoft.Net.Compilers的旧版本(2.10.0)。这是与旧版本 VisualStudio 兼容的最后一个版本。删除该包后,不再提供提示。