2015-07-20 70 views
5

我在C#.NET 4.0中处理一个巨大的项目。有一个继承自System.Net.Sockets.SocketAsyncEventArgs类的自定义类。类似以下内容:如何在继承自SocketAsyncEventArgs的类中实现IDisposable接口

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的源代码(使用转到定义,以便我看到元数据作为源)。我发现,这个类实现了IDisposable接口。很好,我只需要重写Dispose(bool)方法,不是吗? (有关更多详细信息,请参见IDisposable Interface on MSDN,“IDisposable”和“继承层次”部分)。对我来说没有什么新的......不幸的是,让SocketAsyncEventArgs类实现如下:

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

    //some other stuff here 
} 

这意味着,有没有办法如何覆盖的Dispose(布尔)方法,因为它是作为私人代替实施保护 ... 这是什么原因?

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

给继承

处置可以通过其他 对象可以多次调用。当覆盖配置(布尔型)时,请注意不要参考 之前已在之前处理过的对象中处理过的对象 处置。有关如何实施Dispose(布尔型), 的更多信息,请参阅实施处置方法。

等等......什么?

当重写的Dispose(布尔) ...

我怎么重写的Dispose(布尔)?

什么是落实在这种情况下IDisposable接口是推荐的方式?

+1

它不是私有的,它根本没有实现(请参阅http://referencesource.microsoft.com/System/net/System/Net/Sockets/Socket.cs.html#8877)。它确实使用了终结器,但看起来并没有在推荐模式中实现。 –

+0

它看起来像'Dispose'是公开的,而不是'虚拟'。 –

+0

你不应该从该类继承。在现有大型项目中,您可能无法轻松改变这一点。 – usr

回答

3

似乎没有要任何东西从你的子类实现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); 
    } 
} 

提供了以下的输出:

家长被布置。

孩子被处置。

编译器警告有关隐藏父类的Dispose的孩子,所以使用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(); 
    } 
} 

只打印父处理。所以如果你使用这种方法,你必须小心控制对象的生命周期。

+0

感谢您的回答。我同意你的意见,我可以在继承的类上实现IDisposable接口。这实际上是我想到的第一件事情。我只是好奇,如果有人会与另一个来,也许是一个更好的主意。如果在不久的将来没有更好的事情,我会将你的答案标记为已接受。 –