false-positive: Fix this implementation of IDisposable to conform to the dispose pattern

I saw that you already fixed the issue, but in case someone else has the same problem, I will elaborate on the rule requirements.

The idea of this rule is to allow potential derived classes to correctly dispose the members of your class. Hence if your class is sealed, the rule assumes your class correctly disposes itself and does nothing (there is another rule, S2931 which checks if your class contains IDisposable fields that need to be disposed).

If the class is not sealed, the rule checks if it has a base class that implements IDisposable. If it has and your class also implements IDisposable, the rule will recommend to remove your implementation (e.g. remove the IDisposable interface from your class) and override the base class's protected Dispose(bool) method.

If the base class does not implement IDisposable, the rule requires a protected virtual Dispose(bool) method (to allow the inheritors to correctly dispose your class).

If your class contains a finalizer, i.e. destructor, the rule checks if its content is a single invocation of Dispose(false).

The rule checks if the content of the Dispose() method (the one from the interface) contains a single invocation of Dispose(true). If your class has a finalizer, the rule requires an additional call to GC.SuppressFinalize(this).

Basically these are the correct implementations of IDisposable according to the rule:

Sealed class

public sealed class Foo1 : IDisposable
{
    public void Dispose()
    {
        // Cleanup
    }
}

Simple implementation

public class Foo2 : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        // Cleanup
    }
}

Implementation with a finalizer

public class Foo3 : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        // Cleanup
    }

    ~Foo3()
    {
        Dispose(false);
    }
}

Tags:

C#

Sonarqube