如何在继承自 SocketAsyncEventArgs 的 class 中实现 IDisposable 接口

How to implement IDisposable interface in a class inherited from SocketAsyncEventArgs

我在 C# .NET 4.0 中从事一个大型项目。有一个习俗class继承自System.Net.Sockets.SocketAsyncEventArgsclass。类似于以下内容:

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) 方法。

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

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

    //some other stuff here
}

这意味着,无法覆盖 Dispose(bool) 方法,因为它是作为 private 而不是 protected... 这是什么原因?

接下来,我在 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(Boolean)?

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

似乎没有什么可以阻止您在 child class 上实施 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.

编译器会警告在 child 中隐藏 parent class 的处置,因此使用 new 运算符可以消除该警告,只需确保从 child class 调用基础 class Dispose (并以正确的方式实现它)。

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

仅打印出 parent 已处理。因此,如果您使用此方法,则必须小心控制 objects.

的生命周期