[英]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.