private void Dispose(bool)?
本文关键字:bool void Dispose private | 更新日期: 2023-09-27 18:10:03
在一些地方,人们建议将private void Dispose(bool)
用于IDisposable
模式。这似乎过时了(至少对于未密封的类),因为新的建议模式(根据微软)是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"!
}
}
从这里可以看到,它使得使用dispose模式变得非常笨拙。
你可以通过隐藏public void Dispose(void)
然后在某处调用base.Dispose()
来解决这个问题。当调用B b = new B(); b.dispose();
时,这与正确的处置模式"类似",除了调用A b = new B(); b.Dispose();
时,它只调用A
的Dispose
方法。
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");
}
}
总的来说,这整件事看起来很糟糕。我们是否知道这是一个bug, CA接受private void Dispose(bool)
,是否有一种方法,至少抛出一个警告与StyleCop?编辑:我不认为我应该接受Alexandre的回答,因为相对于我的问题,它基本上可以归结为"可能是一个bug",以及一些应该是评论的东西。如果有人有更确凿的答案,我认为这将是一个更合适的答案。
实现Dispose方法
IDisposable接口要求实现一个单节点无参数方法, Dispose。然而, dispose模式需要实现两个dispose方法:public non-virtual(在Visual Basic中是不可继承的)IDisposable。处理没有参数的实现。
- 一个受保护的虚拟(在Visual Basic中可重写)Dispose方法。
因为public,非虚拟的(在Visual Basic中是不可继承的),无参数的Dispose方法是由该类型的使用者调用的,它的目的是释放非托管资源,并指出终结器(如果存在的话)不必运行。因此,它有一个标准实现:
public void Dispose() { // Dispose of unmanaged resources. Dispose (true); // Suppress finalization. GC.SuppressFinalize (this); }
在第二个重载中,Dispose形参是一个布尔值,指示方法调用是来自Dispose方法(其值为true)还是来自终结器(其值为false)。
当垃圾收集器决定不再需要你的对象时,它将尝试结束它,以防你忘记调用无参数的dispose方法,因为如果你这样做了,并且你遵循这个模式,调用将被抑制。
参见:如何完成
私有vs受保护虚拟:
如果你想支持正确遵循模式的子类,你应该像文档所说的那样使用protected virtual。
为什么有些人使用私有版本?可能因为继承从来都不是他们的本意,特别是如果你只是使用Resharper之类的工具动态地生成方法,大多数时候这些方法都是私有的。
为什么代码分析不报告问题?
可能是一个bug。提供一个给出问题的小示例,以便其他人可以在他们的机器上进行测试。