从组件派生并正确实现 IDisposable

Posted

技术标签:

【中文标题】从组件派生并正确实现 IDisposable【英文标题】:Deriving from a component and implementing IDisposable properly 【发布时间】:2011-02-21 22:40:40 【问题描述】:

我有一个 Visual Studio 2008 C# .NET 2.0 CF 项目,其中有一个派生自 Component 的抽象类。从那个类,我派生了几个具体的类(如下面的例子)。 但是,当我退出 Form 时,虽然调用了 Form 的 Dispose() 成员并调用了 components.Dispose(),但我的组件永远不会被释放。

谁能建议我如何修复这个设计?

public abstract class SomeDisposableComponentBase : Component

    private System.ComponentModel.IContainer components;

    protected SomeDisposableComponentBase()
    
        Initializecomponent();
    

    protected SomeDisposableComponentBase(IContainer container)
    
        container.Add(this);
        Initializecomponent();
    

    private void InitializeComponent()
    
        components = new System.ComponentModel.Container();
    

    protected abstract void Foo();

    #region IDisposable Members
    bool disposed_;

    /// Warning 60 CA1063 : Microsoft.Design : Ensure that 'SomeDisposableComponentBase.Dispose()' is declared as public and sealed.*
    public void Dispose()
    
        // never called
        Dispose(true);
        GC.SuppressFinalize(this);
    

    protected virtual void Dispose(bool disposing)
    
        // never called
         if (!disposed_)
        
            if (disposing && (components != null))
            
                components.Dispose();
            
            disposed_ = true;
        
        base.Dispose(disposing);
    
    #endregion    


public SomeDisposableComponent : SomeDisposableComponentBase

    public SomeDisposableComponent() : base()
    
    

    public SomeDisposableComponent(IContainer container) : base(container)
    
    

    protected override void Foo()
    
        // Do something...
    

    protected override void Dispose(bool disposing)
    
        // never called
        base.Dispose(disposing);
    


public partial class my_form : Form

    private SomeDisposableComponentBase d_;

    public my_form()
    
        InitializeComponent();
        if (null == components)
            components = new System.ComponentModel.Container();

        d_ = new SomeDisposableComponent(components);
    

    /// exit button clicked
    private void Exit_Click(object sender, EventArgs e)
    
        this.Close();
    

    /// from the my_form.designer.cs
    protected override void Dispose(bool disposing)
    
        if (disposing && (components != null))
        
            // this function is executed as expected when the form is closed
            components.Dispose();
        
        base.Dispose(disposing);
    

*我注意到 FX-Cop 在这里给了我一个提示。但是,如果我尝试将该函数声明为密封,则会收到错误消息:

error CS0238: 'SomeDisposableComponentBase.Dispose()' cannot be sealed because it is not an override

声明该函数为覆盖会导致:

'SomeDisposableComponentBase.Dispose()': cannot override inherited member 'System.ComponentModel.Component.Dispose()' because it is not marked virtual, abstract, or override

谢谢, 保罗H

【问题讨论】:

【参考方案1】:

SomeDisposableComponentBase 应该覆盖 Component.Dispose(Boolean)

您还需要删除 SomeDisposableComponentBase.Dispose() 方法(不带参数)because it hides the Component.Dispose implementation,因此它们被视为不同的方法,具体取决于您声明变量的方式:

using (Component component = new SomeDisposableComponent()) 
    // Calls Component.Dispose upon exiting the using block


using (SomeDisposableComponentBase component = new SomeDisposableComponent()) 
    // Calls SomeDisposableComponentBase.Dispose upon existing the using block

【讨论】:

【参考方案2】:

发生的事情是编译器将 SomeDisposableComponentBase 上的 Dispose 方法解释为

new public void Dispose() 
 
    // never called 
    Dispose(true); 
    GC.SuppressFinalize(this); 
 

这不是覆盖,它为类层次结构中的现有名称提供了新的语义。所以,实际上您正在创建一个与 Component.Dispose 不同的新 Dispose 方法。

查看Implementing Finalize and Dispose to Clean Up Unmanaged Resources 文章以获取有关如何实现 IDisposable.Dispose 方法的官方指南。

【讨论】:

您说得对,我将删除答案的最后一部分。谢谢。 我很欣赏这个链接。我以前没见过它,它的信息量很大。谢谢。

以上是关于从组件派生并正确实现 IDisposable的主要内容,如果未能解决你的问题,请参考以下文章

哪个类“拥有”非托管资源(并且实现了 IDisposable)?

正确实施 IDisposable

GC.SuppressFinalize()的正确用法

C# IDisposable 正确用法和调用

使用通用虚函数实现的任意组合实现派生类的正确方法是啥?

为啥 Enumerable.Range 实现 IDisposable?