C# 私人无效处置(bool)?
在一些地方,人们建议对C# 私人无效处置(bool)?,c#,code-analysis,idisposable,fxcop,C#,Code Analysis,Idisposable,Fxcop,在一些地方,人们建议对IDisposable模式使用private void Dispose(bool)。但这似乎已经过时(至少对于未密封的类而言),因为新建议的模式(根据Microsoft)是受保护的虚拟void Dispose(bool) 问题是,代码分析不会报告违反的私有void Dispose(bool),即使它似乎直接违反了模式 这是怎么回事?private void Dispose(bool)是否以某种方式被调用(或编译成类似于protected virtual Dispose(bo
IDisposable
模式使用private void Dispose(bool)
。但这似乎已经过时(至少对于未密封的类而言),因为新建议的模式(根据Microsoft)是受保护的虚拟void Dispose(bool)
问题是,代码分析不会报告违反的私有void Dispose(bool)
,即使它似乎直接违反了模式
这是怎么回事?private void Dispose(bool)
是否以某种方式被调用(或编译成类似于protected virtual Dispose(bool)
如果这是代码分析中的一些问题,并且是错误的模式,那么有没有方法检测到这一点?可能是通过StyleCop
编辑:经过考虑,是否基类可以调用base.Dispose()
,这将命中私有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=new B();B.Dispose();
时,它的工作方式与正确的Dispose模式“类似”,除非调用ab=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");
}
}
基本上,这整件事看起来很糟糕。我们知道CA是否接受private void Dispose(bool)
这是一个bug,是否有办法至少向StyleCop发出警告
编辑:我不认为我应该接受Alexandre的答案,因为相对于我的问题,它基本上可以归结为“可能是一个bug”,以及一些应该是评论的东西。如果其他人有更具决定性的东西,我认为这将是一个更合适的答案。
IDisposable接口要求实现单个
无参数方法,Dispose.但是Dispose模式需要实现两种处理方法:
- 公共非虚拟(在Visual Basic中不可继承)IDisposable.Dispose实现,该实现没有参数
- 受保护的虚拟(在Visual Basic中可重写)Dispose方法
public void Dispose()
{
// Dispose of unmanaged resources.
Dispose (true);
// Suppress finalization.
GC.SuppressFinalize (this);
}
在第二个重载中,disposing参数是一个布尔值,指示方法调用是来自Dispose方法(其值为true)还是来自终结器(其值为false)
当垃圾回收器决定不再需要您的对象时,它将尝试完成它,以防您忘记调用无参数dispose方法,因为如果您这样做并且您遵循该模式,则调用将被抑制
见:
私有与受保护虚拟:
如果您想要支持正确遵循该模式的子类,那么应该始终使用受保护的虚拟对象,正如文档中所述
为什么有些人使用私有版本?可能是因为继承从来都不是他们的目的,特别是如果你只是在使用诸如Resharper之类的工具动态生成方法,那么这些方法大部分时间都是私有的
为什么代码分析不报告问题?
可能是一个bug。提供一个小样本来说明问题,以便其他人可以在他们的机器上进行测试。密封类如何?对于开放类应使用Protected,对于密封类应使用private。这两种情况都适用。我们发现了几个未密封类没有引发问题的地方。尽管如此,这个私有类是密封类所必需的。不过,如果该类是未密封的,CA抛出该类会很好(而且它也应该知道这一点)。我认为我的编辑说明了为什么不抛出该类可能不是完全不可能的,但仍然有点烦人。调用
base.Dispose()
显然违反了该模式,因此我不认为它能解释这一点。我同意您最初的想法,即代码分析应该报告您提出的案例。我将使用全部。这篇文章中有很多问题。关键问题是:为什么建议的模式会发生更改,或者为什么代码分析不会发生更改投诉?当bool为真和假时,应该做什么不同的处理(bool)?在页()的末尾您将看到一个示例,如果为true,则必须处置所有资源,因为您调用了dispose方法并希望收回所有使用的内存。如果为false,则表示垃圾收集器正在删除该对象,那么您只需要处置非托管资源(在C#应用程序之外创建的对象),其余的对象可以保持不变,因为垃圾收集器将在需要时删除它们。