C# 误报:修复IDisposable的此实现以符合dispose模式

C# 误报:修复IDisposable的此实现以符合dispose模式,c#,sonarqube,C#,Sonarqube,我的类实现了IDisposable,并遵循以下模式 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } 但声纳仍然告诉我我需要实施处置模式 这是sonar的一个缺陷还是我遗漏了什么?不要在Dispose()方法中调用GC.SuppressFinalize(),除非您的类实现了一个终结器。我看到您已经解决了这个问题,但如果其他人有同样的问题,我将详细说明规则要求 此规则的思想是允许潜在的派生类正

我的类实现了
IDisposable
,并遵循以下模式

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}
但声纳仍然告诉我我需要实施处置模式


这是sonar的一个缺陷还是我遗漏了什么?

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

我看到您已经解决了这个问题,但如果其他人有同样的问题,我将详细说明规则要求

此规则的思想是允许潜在的派生类正确地处理类的成员。因此,如果您的类是密封的,则该规则假定您的类正确地处置了自己,而不执行任何操作(还有另一条规则,它检查您的类是否包含需要处置的
IDisposable
字段)

如果该类未密封,则规则将检查它是否有实现
IDisposable
的基类。如果它有并且您的类也实现了
IDisposable
,则规则将建议删除您的实现(例如,从类中删除
IDisposable
接口),并重写基类的
受保护的Dispose(bool)
方法

如果基类未实现
IDisposable
,则规则需要
受保护的虚拟处置(bool)
方法(以允许继承者正确处置您的类)

如果类包含终结器,即析构函数,则规则将检查其内容是否是对
Dispose(false)
的单个调用

该规则检查
Dispose()
方法(来自接口的方法)的内容是否包含对
Dispose(true)
的单个调用。如果类具有终结器,则该规则需要额外调用
GC.SuppressFinalize(this)

基本上,根据规则,这些是
IDisposable
的正确实现:

密封类

public sealed class Foo1 : IDisposable
{
    public void Dispose()
    {
        // Cleanup
    }
}
简单实现

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

    protected virtual void Dispose(bool disposing)
    {
        // Cleanup
    }
}
使用终结器实施

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

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

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

就我而言,我缺少
virtual
关键字:

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

也许它检测到您没有在类中实现终结器,因此
SuppressFinalize
调用没有效果?另外,您的
Dispose(bool)
应该受到保护吗?这至少是SonarQube明确地说的:
受保护的虚拟无效处置(bool disposing)
1)那么它真的应该这么说,但我使用的模式与我实现的模式相同,2)眼睛好,我会试试看,但不确定它是否在乎1)它实际上在乎:)
TrackedMethodStrategyManager.Dispose()应该只包含对TrackedMethodStrategyManager.Dispose的调用(true),如果类包含终结器,则调用GC.SuppressFinalize(this)。
@MarekFekete-我尝试了受保护的
,因为怀疑它不在乎。接下来,我将尝试第一个建议,看看这是否会击中头部。您是否打算更改sonarqube中的兼容示例以匹配上述内容?是的,我们将更改描述。对我来说,即使我正在实现“简单实现”,例如Foo2,我仍然收到警告。我更改为此处显示的“密封类”实现,以消除警告
GC。如果类未密封,则SuppressFinalize()
必须始终存在,无论类本身是否有终结器。如果其中一个派生类决定实现终结器,则没有合适的方法将其添加到派生类中。另请参见
GC.SuppressFinalize()
,如果类未密封,则必须始终存在,请参见我的上述评论。@Marek:您能详细说明原因吗?@Thariama:仅以我试图从Sonar的消息推断出可能的解决方案的方式;虽然措辞不严格,但这表明声纳可能不需要这个呼叫。至于该规则是否值得遵守,我更倾向于同意@bitbonk-call
SuppressFinalize
,即使您没有实现终结器,derivees将是一个原因,如果您稍后添加终结器,忘记添加它的可能性是另一个原因。