我需要一些关于该Dispose方法实现的建议.
在我们的应用程序中,用户设计自己的UI.我有一个预览窗口,显示UI的外观.此UI中绘制的所有对象最终都来自公共基类ScreenObject.我的预览管理器包含对ScreenGrid的单个对象引用,ScreenGrid是整个预览区域的网格对象.
问题#1
我的一些派生屏幕类保留了非托管资源,例如数据库连接,位图图像和WebBrowser控件.这些类需要处理这些对象.我在基类中创建了一个虚Dispose方法,ScreenObject然后Dispose在每个派生类中实现了一个覆盖非托管资源的覆盖方法.但是,现在我刚刚创建了一个名为的方法Dispose,我没有实现IDisposable.我应该实施IDisposable吗?如果是这样,我该如何实现它?
将虚Dispose方法放在没有非托管资源的基类中是否错误,以便您可以利用多态?
问题2
在阅读有关Dispose方法和IDisposable接口的过程中,Microsoft声明处置对象应该只调用Dispose其父对象的方法.父母将为其父母调用它,依此类推.对我而言,这似乎是倒退.我可能想要处理一个孩子但保留其父母.
我认为它应该是另一种方式,处置的对象应该处理它的孩子.然后孩子们应该处理他们的孩子等等.
我错在这里还是我错过了什么?
PVi*_*itt 36
问题1:IDisposable使用以下模式实施:
public class MyClass : IDisposable
{
bool disposed;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//dispose managed resources
}
}
//dispose unmanaged resources
disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Run Code Online (Sandbox Code Playgroud)
问题2:Microsoft的含义是派生类在其父类上调用dispose.实例的所有者仅在最派生类型上调用Dispose.
一个(缩短的)例子:
class Parent : IDisposable
{
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//dispose managed resources
}
}
//dispose unmanaged resources
disposed = true;
}
}
class Child : Parent, IDisposable
{
protected override void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//dispose managed resources
}
base.Dispose(disposing);
}
//dispose unmanaged resources
disposed = true;
}
}
class Owner:IDisposable
{
Child child = new Child();
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
if(child!=null)
{
child.Dispose();
}
}
}
//dispose unmanaged ressources
disposed = true;
}
}
Run Code Online (Sandbox Code Playgroud)
所有者只调用DisposeChild,但不调用Parent.孩子负责拜访Dispose父母.
根据您列出的对象类型(即数据库,WebBrowser,位图等),就.NET而言,这些只是受管资源.因此,您应该IDisposable在任何具有一次性类型的类上实现成员.如果它们是本地声明的实例,则只需对它们调用'using()'.虽然你提到的这些实例确实有非托管资源,但是这些实际上是通过.NET从你使用的类型中抽象出来的.由于您只使用托管类型,因此应该实现IDisposable 但不使用终结器.如果您真的拥有非托管资源作为类成员,则只需要实现终结器.
看来你将继承(是a)与聚合/包含混淆(有一个).例如,如果"Container"包含一次性资源作为类成员,则称为聚合/包含.因此,调用Container base.Dispose()的IDisposable实现与处理Container 内的可支配资源无关.您应该记住,如果一个类派生自Container,比如说"DerivedContainer",那么它是 Container的一个实例,尽管有其他成员和/或功能.因此,"DerivedContainer"的任何实例都具有其基类"Container"所具有的所有成员.如果你从未打过电话base.Dispose(),那么"容器"中的可支配资源就不会被正确发布(实际上它会由GC发布,但是由于很多原因,只是'让.NET照顾它'是不好的做法) - 请参考我发布的内容回答依赖.NET自动垃圾收集器是不好的做法?.
如果你没有调用基类Dispose(),你最终会得到一个部分处理的对象(放置在派生类中但不在基类中) - 这是一个非常糟糕的场景.因此调用基类非常重要Dispose().
作为一个例子,我在我的博客上写了一个我已经开发的最佳实践模式(有很多经验和调试内存转储).它展示了如何IDisposable在基类和派生类上实现:
http://dave-black.blogspot.com/2011/03/how-do-you-properly-implement.html
| 归档时间: |
|
| 查看次数: |
59247 次 |
| 最近记录: |