如何在从SocketAsyncEventArgs继承的类中实现IDisposable接口

Mar*_*kac 5 c# inheritance dispose idisposable socketasynceventargs

我在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.
    */
}
Run Code Online (Sandbox Code Playgroud)

所以,我想将CleanUp()方法的内容移到Dispose(bool)方法.

首先,我检查了基类的源代码 - SocketAsyncEventArgs(使用Go To Definition,因此我将元数据视为源代码).我发现,这个类实现了IDisposable接口.很好,我只需要覆盖Dispose(bool)方法,不是吗?(有关详细信息,请参阅MSDN上的IDisposable接口," IDisposable和继承层次结构 "部分).对我来说没什么新东西......不幸的是,SocketAsyncEventArgs类实现如下:

public class SocketAsyncEventArgs : EventArgs, IDisposable
{
    public void Dispose();

    //some other stuff here
}
Run Code Online (Sandbox Code Playgroud)

这意味着,没有办法如何覆盖Dispose(bool)方法,因为它实现为私有而不是受保护 ...... 这是什么原因?

接下来,我在MSDN上阅读有关SocketAsyncEventArgs.Dispose()方法的内容.有趣的是,它包含以下部分:

对继承者的说明

可以通过其他对象多次调用Dispose.重写Dispose(布尔值)时,请注意不要引用之前在Dispose调用中 处理过的对象.有关如何实现Dispose(Boolean)的更多信息,请参阅实现Dispose方法.

等等......什么?

当重写Dispose(布尔)时,...

我该如何覆盖Dispose(布尔)?

在这种情况下,推荐使用IDisposable接口的方法是什么?

Ron*_*yer 4

似乎没有什么可以阻止你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);
    }
}
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

父母被处置了。

孩子被处置了。

编译器会警告在子类中隐藏父类的处置,因此使用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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

是的,如果您执行以下操作,这仍然有效:

using (DisposableParent p = new DisposableChild())
{

}
Run Code Online (Sandbox Code Playgroud)

但这样的事情可以打破它:

public class Program
{
    public static void Main()
    {
        DisposableChild c = new DisposableChild();
        DisposeOfIt(c);

        Console.ReadKey(true);
    }

    public static void DisposeOfIt(DisposableParent p)
    {
        p.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

只打印出父母已被处置。因此,如果您使用此方法,则必须小心控制对象的生命周期。