Reputation: 4408
Consider following code:
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()
{
}
}
When I run a code analysis in Visual studio I get a warning:
Warning CA1001 Implement IDisposable on Test.< Do>d__0 because it creates members of the following IDisposable types: 'Disposable'.
Why do I get this message? Disposable class is disposed correctly and I don't store it anywhere.
Furthermore this seems to be OK for analyzer:
public class Test
{
public void Do()
{
using (var disposable = new Disposable())
{
disposable.Do();
}
}
}
Upvotes: 32
Views: 2215
Reputation: 101533
That's because compiler generates state machine from your async method, and that state machine class (named <Do>d__0
in this case) contains field of type Disposable
but does not itself implements IDisposable
interface. It doesn't make much sense for analyzer to analyze compiler generated code (and this <Do>d__0
class is marked with CompilerGenerated
attribute). Fortunately, there is a setting for code analyzer to avoid compiler generated code: go to project properties, "Code Analysis" tab and check "Suppress results from generated code", and this warning will go away.
Upvotes: 29
Reputation: 249
If you look at the IL, you'll find that a class <Do>d__0
is created to handle the async stuff:
// Nested Types
.class nested private auto ansi sealed beforefieldinit '<Do>d__0'
extends [mscorlib]System.Object
implements [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine
{
Later on, this class creates an instance of Disposable:
IL_0074: newobj instance void ConsoleApp1.Disposable::.ctor()
That's the class that triggers CA1001 because CA1001 checks the IL, and the generated class does not implement IDisposable
. You can safely disregard the CA1001 warning on this particular class.
Upvotes: 10