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: "Одноразовые".

Почему я получаю это сообщение? Одноразовый класс расположен правильно, и я его не хранил.

Кроме того, для анализатора это выглядит нормально:

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

Ответы

Ответ 1

Это потому, что компилятор генерирует <Do>d__0 автомат из вашего метода async, а этот класс <Do>d__0 автомата (с именем <Do>d__0 в этом случае) содержит поле типа Disposable но сам не реализует интерфейс IDisposable. Анализатор не имеет смысла анализировать генерируемый компилятором код (и этот класс <Do>d__0 помечен атрибутом CompilerGenerated). К счастью, для анализатора кода есть возможность избежать компилятора сгенерированного кода: перейдите к свойствам проекта, вкладке "Анализ кода" и установите флажок "Подавлять результаты сгенерированного кода", и это предупреждение исчезнет.

Ответ 2

Если вы посмотрите на IL, вы обнаружите, что класс <Do>d__0 создан для обработки асинхронных <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
{

Позже этот класс создает экземпляр одноразового использования:

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

Тот класс, который запускает CA1001, потому что CA1001 проверяет IL, а сгенерированный класс не реализует IDisposable. Вы можете смело игнорировать предупреждение CA1001 в этом конкретном классе.