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-callSuppressFinalize
,即使您没有实现终结器,derivees将是一个原因,如果您稍后添加终结器,忘记添加它的可能性是另一个原因。