在 C# 中 parent 类 上正确实现 IDisposable

Implementing IDisposable correctly on parent classes in C#

我有一个 class 实现了 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,所以我想我应该让我的 class 成为 SerialPort 的 child,但现在我收到警告说我似乎无法修复。

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

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

"Warning CA1063 Ensure that 'AsyncSerial.Dispose()' is declared as public and sealed"

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

Error CS0506 'AsyncSerial.Dispose()': cannot override inherited member 'Component.Dispose()' because it is not marked virtual, abstract, or override

我不知道 'correct' 在 parent class 中用 IDisposable 实现处置 class 的方法。我发现的每个例子都只适合以 IDisposable 作为基础,但让我的 class

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

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

我是否应该只取消有关确保 'AsyncSerial.Dispose()' 被声明为 public 并密封的警告,或者是否有正确的方法来执行此操作而不会给出代码分析警告。

你的 subclass 应该覆盖 Dispose(bool disposing) 如果有的话——这就是拥有该方法的全部意义,真的。

但是,我怀疑基础 class 无论如何都会做出正确的调用,所以你不需要做任何事情,除非你有额外的资源来释放 没有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 
}

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

您不需要在 child class 上声明 public void Dispose() 方法,因为它已经从基础方法中继承了(反正编译器不会让您这样做的) ,除非您使用 new 关键字隐藏基本实现。

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

如果您要在 child class 中使用 IDisposable 引用,那么您应该 覆盖 您的基础 class的方法:

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

处置模式旨在允许派生类型以一致的方式添加处置逻辑,而不管父类型是否具有 public Dispose 方法或显式实现 IDisposable.Dispose。从遵循模式的类型派生的类型应该简单地覆盖 Dispose(bool) 而不管父 class 实现如何使用 public 方法或 IDisposable.Dispose().[=15 的显式实现=]

虽然 Dispose 模式的设计是基于这样一个有缺陷的假设,即 publicly-exposed 可继承类型的对象通常需要直接合并终结器(而不是将非托管资源封装在私有中-held 私有类型的实例,其目的是清理这些资源),编译器在 C++/CLI(可能还有其他语言)中生成的清理逻辑依赖于该模式,因此将它与可继承的 classes 可能被其他人使用。