web-dev-qa-db-ja.com

CA1001は非同期メソッドにIDisposableを実装します

次のコードを検討してください。

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を実装します。<Do> d__0は、次のIDisposableタイプのメンバーを作成するためです: 'Disposable'。

このメッセージが表示されるのはなぜですか?使い捨てクラスは正しく破棄され、どこにも保存していません。

さらに、これはアナライザーにとっては問題ないようです:

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

これは、コンパイラが非同期メソッドからステートマシンを生成し、そのステートマシンクラス(<Do>d__0(この場合)には、タイプDisposableのフィールドが含まれていますが、それ自体はIDisposableインターフェースを実装していません。アナライザーがコンパイラーが生成したコードを分析することはあまり意味がありません(そしてこの<Do>d__0クラスはCompilerGenerated属性でマークされます)。幸い、コンパイラーが生成したコードを回避するコードアナライザーの設定があります。プロジェクトのプロパティの[コード分析]タブに移動し、[生成されたコードの結果を表示しない]をオンにすると、この警告は表示されなくなります。

28
Evk

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はILをチェックし、生成されたクラスはIDisposableを実装しないため、これがCA1001をトリガーするクラスです。この特定のクラスに関するCA1001警告は無視しても問題ありません。

10
Thomas Radioyes