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 в этом конкретном классе.