【问题标题】:CA1001 implement IDisposable on async methodCA1001 在异步方法上实现 IDisposable
【发布时间】:2018-06-14 04:42:21
【问题描述】:

考虑以下代码:

public class Test
{
    public async Task Do()
    {
        await Task.Delay(200);

        using (var disposable = new Disposable())
        {
            disposable.Do();
        }
    }
}

public class Disposable : IDisposable
{
    public void Do()
    {
    }

    public void Dispose()
    {
    }
}

当我在 Visual Studio 中运行代码分析时,我收到一条警告:

警告 CA1001 在测试时实施 IDisposable。d__0 因为它创建了以下 IDisposable 类型的成员:'Disposable'。

为什么我会收到此消息? Disposable 类已正确处理,我不会将其存储在任何地方。

此外,这对分析器来说似乎没问题:

public class Test
{
    public void Do()
    {
        using (var disposable = new Disposable())
        {
            disposable.Do();
        }
    }
}

【问题讨论】:

  • 可以说是分析器中的一个错误。编译器将其转换为状态机代码,其中一次性被提升到一个闭包类中,将变量公开为一个字段,然后代码分析会发出警告。它不知道编译器生成的代码在任何情况下都会处理对象,并且该类不打算由客户端处理。由于用户显然无法在任何情况下修改编译器生成的代码,因此警告毫无意义(即使编译器生成的代码应该包含错误!)

标签: c# .net visual-studio async-await code-analysis


【解决方案1】:

这是因为编译器从您的异步方法生成状态机,并且该状态机类(在本例中名为 <Do>d__0)包含 Disposable 类型的字段,但它本身并不实现 IDisposable 接口。分析器分析编译器生成的代码没有多大意义(并且这个<Do>d__0 类标有CompilerGenerated 属性)。幸运的是,代码分析器有一个设置可以避免编译器生成代码:进入项目属性,“代码分析”选项卡并选中“抑制生成代码的结果”,此警告将消失。

【讨论】:

  • 我已经检查了设置,但我仍然收到错误任何想法为什么?
【解决方案2】:

如果您查看 IL,您会发现创建了一个类 <Do>d__0 来处理异步内容:

// Nested Types
.class nested private auto ansi sealed beforefieldinit '<Do>d__0'
    extends [mscorlib]System.Object
    implements [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine
{

稍后,这个类会创建一个 Disposable 的实例:

IL_0074: newobj instance void ConsoleApp1.Disposable::.ctor()

那是触发CA1001的类,因为CA1001检查IL,生成的类没有实现IDisposable。您可以放心地忽略此特定类的 CA1001 警告。

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 2019-10-16
    • 1970-01-01
    相关资源
    最近更新 更多