繁体   English   中英

在C#中的父类上正确实现IDisposable

[英]Implementing IDisposable correctly on parent classes in C#

我有一个实现C# SerialPort的类,它常常如下所示:

public class AsyncSerial : IDisposable
{
    SerialPort newPort; //Parameters declared in my constructor
    //Constructor and other methods

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if(disposing)
        {
            this.Close();
            this.Dispose();
        }
    }
}

这在代码分析中不会引发任何警告(我从MSDN获取代码作为如何正确执行此操作的示例)。

由于我只是要声明一个SerialPort我想我会让我的班级成为SerialPort的孩子,但现在我收到警告,我似乎无法修复。

public class AsyncSerial : SerialPort
{
    //Constructor and other methods

    public new void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected new virtual void Dispose(bool disposing)
    {
        if(disposing)
        {
            this.Close();
            this.Dispose();
        }
    }
}

代码警告说处理方法应该是new因为它们隐藏了成员,我做了,但我也得到:

“警告CA1063确保'AsyncSerial.Dispose()'被声明为公共密封”

使其密封意味着它必须被标记为override (或者我得到编译器错误),使其覆盖意味着它可以是新的,所以我最终得到:

错误CS0506'AsyncSerial.Dispose()':无法覆盖继承的成员'Component.Dispose()',因为它未标记为虚拟,抽象或覆盖

我不知道在父类中使用IDisposable实现处理的“正确”方法。 我找到的每个例子都只适合以IDisposable作为基础,但是我的课程

public class AsyncSerial : SerialPort, IDisposable
{
    //code
}

给我一个代码分析警告,因为SerialPort已经实现了IDisposable

我是否应该禁止关于确保'AsyncSerial.Dispose()'被声明为公共和密封的警告,或者是否有正确的方法来执行此操作而不提供代码分析警告。

如果有的话,你的子类应该重写Dispose(bool disposing) - 这就是完全拥有该方法的全部意义。

但是,我怀疑基类无论如何都会进行正确的调用,所以你不需要做任何事情,除非你有额外的资源要释放, 而不是Close()释放。 如果是这种情况,请在Dispose(bool disposing)

protected override void Dispose(bool disposing)
{
    // Allow the base class to release resources
    base.Dispose(disposing);
    // Release any extra resources here 
}

请注意,您的当前实现将导致StackOverflowException,因为您的两个Dispose重载相互调用。

Dispose Pattern旨在允许派生类型以一致的方式添加处理逻辑,而不考虑父类型是否具有公共Dispose方法或显式实现IDisposable.Dispose 从模式后面的类型派生的类型应该简单地重写Dispose(bool)无论父类如何使用公共方法或IDisposable.Dispose()显式实现。

尽管Dispose模式的设计基于以下缺陷:假设公开的可继承类型对象通常需要直接合并终结器(而不是将非托管资源封装在私有类型的私有实例中,其目的是清理这些资源) ),C ++ / CLI中编译器生成的清理逻辑(也可能是其他语言)依赖于模式,因此将它与可由其他人使用的可继承类一起使用是个好主意。

您不需要在子类上声明一个public void Dispose()方法,因为它已经从基类继承(编译器不会允许您,除非您使用new关键字隐藏基本实现)。

如果您不打算处理特定于此子类的任何内容,则也不需要覆盖基类的protected virtual void Dispose(bool)

如果您的子类中有IDisposable引用,那么您应该覆盖基类的方法:

public class AsyncSerial : SerialPort, IDisposable
{
    // SomeClass implements IDisposable
    private SomeClass _disposableInstance;

    // ...

    protected override void Dispose(bool disposing)
    {
        if(disposing)
        {
            if(_disposableInstance != null)
                _disposableInstance.Dispose();
        }

        // Call the base Dispose, to release resources on the base class.
        base.Dipose(disposing);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM