C#如何实现Dispose方法

我需要一些关于Dispose方法实现的建议。

在我们的应用程序中,用户设计自己的UI。 我有一个预览窗口,显示UI的外观。 在这个用户界面中绘制的所有对象最终都来自一个公共基类ScreenObject。 我的预览管理器包含对ScreenGrid的单个对象引用,这是整个预览区域的网格对象。

问题#1

我的一些派生屏幕类保存非托管资源,如数据库连接,位图图像和WebBrowser控件。 这些类需要处理这些对象。 我在基础ScreenObject基类中创建了一个虚拟的Dispose方法,然后在每个派生类中实现了一个覆盖Dispose方法,该派生类保存了非托管资源。 但是,现在我刚刚创建了一个名为Dispose的方法,我没有实现IDisposable。 我应该实施IDisposable吗? 如果是这样,我该如何执行它?

  • 就在具有非托管资源的派生类上
  • 具有非托管资源OR的基类和派生类
  • 基类和所有派生类,包括那些没有非托管资源的派生类
  • 将虚拟Dispose方法放在没有非托管资源的基类中是否错误,以便您可以利用多态性?

    问题2

    在阅读有关Dispose方法和IDispoable接口的信息时,Microsoft声明处置对象应该只为其父级调用Dispose方法。 父母会将其称为父母等。 对我来说这似乎倒退了。 我可能想要处理一个孩子,但保留其父母。

    我认为这应该是相反的方式,一个处理对象应该处理其子女。 然后,孩子们应该处理他们的孩子,等等。

    我在这里错了还是错过了什么?


    问题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);
        }
    }
    

    问题2:微软的意思是派生类调用它的父类。 实例的所有者仅在最派生的类型上调用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;
        }
    }
    

    所有者只在子项上调用Dispose,但不在父项上调用。 孩子负责调用父母的Dispose。


    对于问题1:
    根据您列出的对象类型(即数据库,Web浏览器,位图等),这些只是.NET的管理资源。 因此,您应该在任何类型为成员的类上实现IDisposable。 如果它们是本地声明的实例,则只需在它们上调用'using()'即可。 尽管您提到的这些实例具有非托管资源,但.NET通过您使用的类型将其抽离。 由于您只使用托管类型,因此您应该实现IDisposable, 但不包含终结器 。 如果您确实拥有非托管资源作为类成员,则只需实现终结器。

    对于问题2:
    看来你混淆了继承(是)与聚合/遏制(有一个)。 例如,如果“容器”包含一次性资源作为类成员,则称为聚合/包含。 因此,在Container的IDisposable实现中调用“base.Dispose()”与处理Container内的可用资源无关。 你应该记住,如果一个类从Container派生出来,比如说“DerivedContainer”,那么它就是Container的一个实例,尽管有额外的成员和/或功能。 因此,“DerivedContainer”的任何实例都具有其基类“Container”所具有的所有成员。 如果您从未调用过base.Dispose(),那么“Container”中的可用资源将无法正确释放(它实际上是由GC进行的,但由于许多原因让'.NET处理它'成为坏习惯)请参考我发布的答案是不好的做法依赖于.NET自动垃圾回收器?

    如果你没有调用基类Dispose(),你最终会得到一个部分处理的对象(放置在派生类中,但不在基类中) - 这是一个非常糟糕的情况。 所以调用基类Dispose()非常重要。

    我有一个我的博客上开发的最佳实践模式(有很多经验和调试内存转储)作为示例。 它演示了如何在基类和派生类上实现IDisposable:

    http://dave-black.blogspot.com/2011/03/how-do-you-properly-implement.html

    如果这篇文章有帮助,请将其标记为这样。 HTH

    链接地址: http://www.djcxy.com/p/54459.html

    上一篇: C# how to implement Dispose method

    下一篇: Implementing IDisposable with empty Dispose for reasons of readability