C#如何实现Dispose方法

发布于 2024-12-05 15:39:43 字数 979 浏览 0 评论 0原文

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

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

问题 #1

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

  • 仅在具有非托管资源的派生类上
  • 具有非托管资源的基类和派生类 OR
  • 基类和所有派生类,包括那些不具有非托管资源的派生类

放置虚拟 是否错误code>Dispose 方法位于没有非托管资源的基类中,以便您可以利用多态性?

问题 #2

在阅读有关 Dispose 方法和 IDisposable 接口时,Microsoft 指出处置对象应该只调用 Dispose 其父方法。父级将为其父级调用它,依此类推。对我来说,这似乎是倒退的。我可能想处置一个孩子,但保留其父母。

我认为应该是相反的,一个被处理的对象应该处理它的子对象。然后孩子们应该处理掉他们的孩子等等。

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

I need some advice on the implementation of the Dispose method.

In our application the user designs their own UI. I have a preview window that shows what the UI is going to look like. All object drawn in this UI ultimately derive from a common base class ScreenObject. My preview manager contain a single object reference to a ScreenGrid which is the grid object for the entire preview area.

Question #1

Some of my derived screen classes hold onto unmanaged resources, such as a database connection, bitmap image and a WebBrowser control. These classes need to dispose of these objects. I created a virtual Dispose method in the base ScreenObject base class and then implemented an override Dispose method in each of the derived classes that hold onto unmanaged resources. However, right now I just created a method called Dispose, I am not implementing IDisposable. Should I implement IDisposable? If so how do I implement it?

  • Just on the derived classes that have unmanaged resources
  • The base class and derived classes that have unmanaged resources OR
  • The base class and all derived classes including those that do not have unmanaged resources

Is it wrong to put a virtual Dispose method in a base class that doesn't have unmanaged resources so that you can take advantage of polymorphism?

Question #2

In reading about the Dispose method and the IDisposable interface Microsoft states that the disposing object should only call the Dispose method for its parent. The parent will call it for its parent and so on. To me this seems backwards. I may want to dispose of a child but keep its parent around.

I would think it should be the other way around, an object being disposed should dispose of its children. The children should then dispose of their children and so on.

Am I wrong here or am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

墨小沫ゞ 2024-12-12 15:39:43

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

所有者仅对子级调用 Dispose,但不对父级调用。子级负责调用父级上的Dispose

Question 1: Implement IDisposable as well, using the following pattern:

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

Question 2: What Microsoft means is that a derived class calls dispose on it's parent class. The owner of the instance only calls Dispose on the most derived type.

An (shortened) example:

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;
    }
}

The owner only calls Dispose on the Child, but not on the Parent. The Child is responsible for calling Dispose on the Parent.

三生一梦 2024-12-12 15:39:43

问题 1:

根据您列出的对象类型(即数据库、Web 浏览器、位图等),就 .NET 而言,这些只是托管资源。因此,您应该在任何具有一次性类型作为成员的类上实现IDisposable。如果它们是本地声明的实例,您只需对它们调用“using()”即可。虽然您提到的这些实例确实具有非托管资源,但 .NET 通过您正在使用的类型将其从您那里抽象出来。由于您仅使用托管类型,因此您应该实现 IDisposable 但不使用终结器。如果您确实拥有非托管资源作为类成员,则只需实现终结器。

问题 2:

您似乎将继承 (is a) 与聚合/包含 (has a) 混淆了。例如,如果“Container”包含一次性资源作为类成员,则称为聚合/包含。因此,在 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

Question 1:

Based on the types of objects that you list (i.e. Database, WebBrowser, Bitmap, etc.) these are only managed resources as far as .NET is concerned. Thus, you should implement IDisposable on any class that has disposable types as members. If they are locally declared instances, you just call 'using()' on them. While these instances you mention do have unmanaged resources under them, this is abstracted away from you by .NET thru the types you are using. Since you are only using managed types, you should implement IDisposable but without a finalizer. You only need to implement a finalizer if you truly have unmanaged resources as class members.

Question 2:

It seems that you are confusing inheritance (is a) with aggregation/containment (has a). For example, if "Container" contains a disposable resource as a class member, it is called aggregation/containment. So, calling base.Dispose() in the IDisposable implementation of Container has nothing to do with disposing of the disposable resource inside of Container. You should remember that if a class derives from Container, say "DerivedContainer", that it is an instance of Container albeit with additional members and/or functionality. So any instance of "DerivedContainer" has all of the members that its base class "Container" does. If you never called base.Dispose(), the disposable resource in "Container" would not be released properly (it would actually by the GC, but it's bad practice for many reasons to just 'let .NET take care of it') - please refer to my posted answer at Is it bad practice to depend on the .NET automated garbage collector?.

If you didn't call the base class Dispose(), you'd end up with a partially disposed object (disposed in the derived class but not in the base class) - a very bad scenario. So it is very important to call the base class Dispose().

I have a best practices pattern I've developed (with lots of experience and debugging memory dumps) written on my blog as an example. It shows how to implement IDisposable on a base class as well as a derived class:

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

北方的巷 2024-12-12 15:39:43

我实现了IDisposable

 class ConnectionConfiguration:IDisposable
{
    private static volatile IConnection _rbMqconnection;
    private static readonly object ConnectionLock = new object();
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (!disposing)
        {
            return;
        }
        if (_rbMqconnection == null)
        {
            return;
        }
        lock (ConnectionLock)
        {
            if (_rbMqconnection == null)
            {
                return;
            }
            _rbMqconnection?.Dispose();//double check
            _rbMqconnection = null;
        }
    }
}

I Implement IDisposable

 class ConnectionConfiguration:IDisposable
{
    private static volatile IConnection _rbMqconnection;
    private static readonly object ConnectionLock = new object();
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (!disposing)
        {
            return;
        }
        if (_rbMqconnection == null)
        {
            return;
        }
        lock (ConnectionLock)
        {
            if (_rbMqconnection == null)
            {
                return;
            }
            _rbMqconnection?.Dispose();//double check
            _rbMqconnection = null;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文