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