简体   繁体   中英

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

My class implements IDisposable and follows the pattern where

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

But sonar is still telling me I need to implement the dispose pattern...

https://sonarqube.com/issues#issues=AVtsPLjmtpYg8Dj4z0MU

Is this a defect with sonar or have I missed something?

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 (eg 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, ie 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);
    }
}

不要在Dispose()方法中调用GC.SuppressFinalize() ,除非您的类实现了终结器。

In my case I was missing virtual keyword:

private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
    if (!disposed && disposing)
    {
        _dbContext.Dispose();
    }
    disposed = true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM