【问题标题】:csharp_prefer_simple_using_statement / IDE0063 Not Appearing When Expectedcsharp_prefer_simple_using_statement / IDE0063 未按预期出现
【发布时间】:2022-08-22 02:06:08
【问题描述】:

我没有看到代码分析规则csharp_prefer_simple_using_statement aka \"Use simple \'using\' statement (IDE0063)\" 在预期时产生输出。我在项目中的方法中添加了一些虚拟代码,如下所示:

using (var file = Image.FromFile(userName))
{
    System.Diagnostics.Debug.Assert(file != null);
}

我在 VS 2022 中的 .sln 样式解决方案包括几个 .csproj 样式项目(即“旧方式”)。我的 .sln 文件夹中有一个 .editorconfig 文件,其他各种内置的 .NET 分析器和 Roslynator 分析器都可以正常工作。

在 .editorconfig 我有csharp_prefer_simple_using_statement = true:warning,我 还添加了dotnet_diagnostic.IDE0063.severity = warning 以获得良好的衡量标准。我已经仔细检查过配置中的其他地方都没有重复,并且解决方案/项目文件夹中的任何地方都没有其他 .editorconfig 文件。

尽管我知道它应该被 .editorconfig 文件取代,但我在 VS Options 中找到了相同的设置并在那里启用了它:

我还打开了项目文件(C# 10 / .NET 6 最新版本,顺便说一句),并设置 <AnalysisLevel>latest-recommended</AnalysisLevel>

我已经清理了构建,重新启动 VS 并重新构建,但在输出、错误列表或编辑器中仍然没有看到任何内容,表明它建议简化 using 语句。再一次,我有许多产品输出的其他代码分析规则既存在于编辑器中,也存在于构建输出和错误列表中。

请问我哪里错了?

编辑:@Guru Stron 的问题激怒了我的感觉,我发现虽然这里的第一种方法确实如此不是产生IDE0063,后者做。为什么?

public Stream GenerateReport()
{
    using (var reportContext = new ReportRenderContext(this.ReportTemplate))
    {
        reportContext.Render();
    }

    return this.FileStream;
}

public static int GetAreaOfImage(string fileName)
{
    using (var image = Image.FromFile(fileName))
    {
        return image.Size.Width * image.Size.Height;
    }
}
  • 是否提供了一个完整的代码 sn-p?你能发布完整的方法代码吗?
  • @GuruStron 编辑了 OP 以解决您的问题。您知道 IDE0063 不退出的情况吗?
  • 是的,我的猜测是您在using 之后有一些语句,因此编译器不会因为一次性资源的范围不同而触发警告。

标签: c# code-analysis visual-studio-2022 roslyn-code-analysis c#-10.0


【解决方案1】:

using declaration 基于作用域工作,资源会在作用域结束时被释放,所以下一个:

public Stream GenerateReport()
{
    using (var reportContext = new ReportRenderContext(this.ReportTemplate))
    {
        reportContext.Render();
    }

    return this.FileStream;
}

不类似于:

public Stream GenerateReport()
{
    using var reportContext = new ReportRenderContext(this.ReportTemplate);
    reportContext.Render();
    return this.FileStream;
}

后者类似于:

public Stream GenerateReport()
{
    using (var reportContext = new ReportRenderContext(this.ReportTemplate))
    {
        reportContext.Render();
        return this.FileStream;
    }
} 

在某些情况下可能会有所不同,因此由于此编译器不会产生警告(编译器同时非常聪明和愚蠢,它并不“真正”知道this.FileStream 做了什么。例如,它可以访问与ReportRenderContext 相同的资源(例如一些不可共享的文件)并在return this.FileStream 之后处理会引入运行时错误。或者this.FileStream 可能只是一个相对较长的操作,而Dispose 的主要目的之一是在不需要资源时立即释放资源。有一个“反向”示例,即第二个 sn-p 可以修复“错误”-async context)。

【讨论】:

  • 我得到了一般理论,但在实践中我不明白其中的区别。如果 using 声明在当前作用域的末尾进行处理,那么它会在 return 语句之后但在调用方法中继续执行之前进行处理,对吗?这与您答案中的第三个代码块不完全相同吗?
  • @pbarranis 2nd 和 3rd 是相同的,正如我在回答中所写的那样(如果是 3rd,你应该收到警告)。但是第一个与第二个和第三个不同。
  • @gurustrong我看到它会在稍后处理reportContext;这是我没有得到 IDE0063 的唯一原因吗?两者之间还有其他我不理解的区别吗?
  • @pbarranis 是的,因为编译器同时非常聪明和愚蠢。它不知道this.FileStream 做了什么。例如,它可以访问与ReportRenderContext 相同的资源(例如某些不可共享的文件)并且在return this.FileStream 之后处理会引入运行时错误。或者this.FileStream 可能只是一个相对较长的操作,而Dispose 的全部目的是在不需要资源时立即释放资源。当第二个 sn-p 可以修复“错误”时,有一个“反向”示例 - in async context
猜你喜欢
  • 2017-02-23
  • 1970-01-01
  • 2018-10-01
  • 2014-09-29
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
  • 2014-09-18
  • 2012-09-24
相关资源
最近更新 更多