在某些地方,人们建议使用private void Dispose(bool)
作为IDisposable
模式。这似乎已经过时了(至少对于未密封的类),因为新建议的模式(根据Microsoft)是protected virtual void Dispose(bool)
。
问题是,代码分析不会报告private void Dispose(bool)
违反CA1063,即使它似乎直接违反了该模式。
这是怎么回事?是private void Dispose(bool)
以某种方式被调用(或编译为看起来像protected virtual Dispose(bool)
的东西吗?
如果这是代码分析的一些问题并且是不正确的模式,有没有办法检测到这个?可能还有StyleCop?
编辑:经过考虑后,基类是否可以调用base.Dispose()
来点击private void Dispose(bool)
?即使它无法传递参数?
编辑:示例
public class A : IDisposable
{
~A()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) // Should be protected virtual void Dispose(bool)
{
Console.WriteLine("A");
}
}
public class B : A
{
protected virtual void Dispose(bool disposing) // Proper pattern.
{
Console.WriteLine("B");
}
}
public static class Program
{
static void Main(string[] args)
{
A a = new A();
a.Dispose(); // Prints "A"
B b = new B();
b.Dispose(); // Prints "A"!
}
}
从这一点可以看出,它使得处理模式完全笨拙。
你可以通过隐藏public void Dispose(void)
然后在某个地方调用base.Dispose()
来解决这个问题。在调用B b = new B(); b.dispose();
时调用A b = new B(); b.Dispose();
除了之外,这与正确的处置模式“相似”,后者仅调用A
的{{1}}方法
Dispose
基本上,整件事看起来很糟糕。我们是否知道它是否是CA接受public class B : A
{
public void Dispose() // Causes CA error with or without "new".
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) // Proper pattern.
{
base.Dispose(); // Writes "A" (without quotes).
Console.WriteLine("B");
}
}
的错误,是否有办法至少向StyleCop发出警告?
编辑:我认为我不应该接受亚历山大的回答,因为相对于我所拥有的问题,它基本上归结为“可能是一个错误”,以及应该作为评论的内容。如果其他人有更具决定性的东西,我认为这将是一个更合适的答案。
答案 0 :(得分:6)
IDisposable 界面需要 单一的实施 无参数方法,Dispose。 然而,配置模式需要 两个Dispose方法:
- 公共非虚拟(在Visual Basic中为NonInheritable)IDisposable.Dispose实现,没有参数。
- 受保护的虚拟(在Visual Basic中可覆盖)Dispose方法。
因为 public ,非虚拟(在Visual Basic中为NonInheritable),无参数Dispose方法由该类型的使用者调用,其目的是释放非托管资源并指示终结者,如果存在,则不必运行。因此,它有一个标准的实现:
public void Dispose() { // Dispose of unmanaged resources. Dispose (true); // Suppress finalization. GC.SuppressFinalize (this); }
在第二个重载中,disposing参数是一个布尔值,指示方法调用是来自Dispose方法(其值是true)还是来自终结器(其值为false)。 / p>
当垃圾收集器决定不再需要你的对象时,如果你忘记调用无参数的dispose方法,它会尝试完成它,因为如果你这样做并且你正在遵循这个模式,那么调用将会被抑制
如果你想要支持正确遵循模式的子类,你应该总是使用受保护的虚拟文件,如文档所示。
为什么有些人使用私有版本?也许是因为继承从来就不是他们的意图,特别是如果你只是使用像Resharper这样的工具动态生成方法,大多数时候这些方法都是私有的。
可能是个错误。提供一个小样本来解决问题,以便其他人可以在他们的机器上进行测试。