在C#中

时间:2015-12-16 11:58:05

标签: c# design-patterns idisposable

我有一个实现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()'被声明为公共和密封的警告,或者是否有正确的方法来执行此操作而不提供代码分析警告。

3 个答案:

答案 0 :(得分:8)

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

但是,我怀疑基类会进行正确的调用,所以你不需要做任何事情,除非你有额外的资源来释放{em>不是在{{ 1}}。如果是这种情况,请在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。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

你不需要在子类上声明一个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);
    }
}