我在C#.NET 4.0中处理一个庞大的项目.有一个从System.Net.Sockets.SocketAsyncEventArgs类继承的自定义类.类似于以下内容:
public class SocketTaskArgs : SocketAsyncEventArgs
{
public SocketTaskArgs()
{
Completed += someEventhHandler;
}
public void CleanUp()
{
Completed -= someEventhHandler;
}
/*
There is a lot of code here that is unimportant at the moment.
*/
}
所以,我想将CleanUp()方法的内容移到Dispose(bool)方法.
首先,我检查了基类的源代码 – SocketAsyncEventArgs(使用Go To Definition,因此我将元数据视为源代码).我发现,这个类实现了IDisposable接口.很好,我只需要覆盖Dispose(bool)方法,不是吗? (有关详细信息,请参阅IDisposable Interface on MSDN,“IDisposable和继承层次结构”部分).对我来说没什么新东西……不幸的是,SocketAsyncEventArgs类实现如下:
public class SocketAsyncEventArgs : EventArgs,IDisposable
{
public void Dispose();
//some other stuff here
}
这意味着,没有办法如何覆盖Dispose(bool)方法,因为它实现为私有而不是受保护……这是什么原因?
接下来,我在MSDN上阅读了有关SocketAsyncEventArgs.Dispose()方法的内容.有趣的是,它包含以下部分:
Notes to Inheritors
Dispose can be called multiple times by other
objects. When overriding Dispose(Boolean),be careful not to reference
objects that have been prevIoUsly disposed of in an earlier call to
Dispose. For more information about how to implement Dispose(Boolean),
see Implementing a Dispose Method.
等等……什么?
When overriding Dispose(Boolean),…
我该如何覆盖Dispose(布尔)?
在这种情况下,推荐使用IDisposable接口的方法是什么?
public class DisposableParent : IDisposable
{
public void Dispose()
{
Console.WriteLine("The parent was disposed.");
}
}
public class DisposableChild : DisposableParent,IDisposable
{
public new void Dispose()
{
base.Dispose();
Console.WriteLine("The child was disposed.");
}
}
public class Program
{
public static void Main()
{
using (DisposableChild c = new DisposableChild()) { }
Console.ReadKey(true);
}
}
给出以下输出:
The parent was disposed.
The child was disposed.
编译器警告隐藏子类中父类的处置,因此使用new运算符去除该警告,只需确保从子类调用基类Dispose(并以正确的方式实现).
对孩子的处置将变成如下:
public class DisposableChild : DisposableParent,IDisposable
{
private bool _disposed = false;
public new void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (!_disposed)
{
base.Dispose();
Console.WriteLine("The child was disposed.");
_disposed = true;
}
}
}
}
是的,如果您执行以下操作,这仍然有效:
using (DisposableParent p = new DisposableChild())
{
}
但这样的事情可以打破它:
public class Program
{
public static void Main()
{
DisposableChild c = new DisposableChild();
DispoSEOfIt(c);
Console.ReadKey(true);
}
public static void DispoSEOfIt(DisposableParent p)
{
p.Dispose();
}
}