How to implement the IDisposable interface in a class inherited from SocketAsyncEventArgs

I am working on a huge project in C # .NET 4.0. There is a special class inherited from System.Net.Sockets. SocketAsyncEventArgs class. Something like the following:

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. */ } 

So, I wanted to move the contents of the CleanUp () method to the Dispose (bool) method.

As a first, I checked the source code of the base class - SocketAsyncEventArgs (using Go to Definition so that I see metadata as a source). I found out that this class implements the IDisposable interface. Nice, I just need to override the Dispose (bool) method, right? (For more information, see IDisposable Interface on MSDN , section "IDisposable and Inheritance Hierarchy"). Nothing new for me ... Unfortunately, the SocketAsyncEventArgs class is implemented as follows:

 public class SocketAsyncEventArgs : EventArgs, IDisposable { public void Dispose(); //some other stuff here } 

This means that there is no way to override the Dispose (bool) method, since it is implemented as private rather than protected ... What is the reason for this?

Next, I read the SocketAsyncEventArgs.Dispose () method on MSDN. The funny thing is that it contains the following section:

Notes to the heirs

Dispose can be called several times by other objects. When overriding Dispose (Boolean), be careful not to reference objects that were previously deleted in an earlier call to Dispose . For more information on how to implement Dispose (Boolean) , see "Implementing the Removal Method".

Wait ... what?

When overriding Dispose (Boolean) , ...

How do I override Dispose (Boolean)?

What is the recommended way to implement the IDisposable interface in this case?

+5
source share
1 answer

It seems you have nothing to interfere with implementing IDisposable in your child class, take this example:

 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); } } 

Gives the following output:

The parent has been deleted.

The baby has been removed.

The compiler warns that it hides the allocation of the parent class in the child, so using the new operator eliminates this warning, just make sure you call the base Dispose class from the child class (and implement its correct path).

The utility for the child will become something like:

 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; } } } } 

And yes, this works if you do something like:

 using (DisposableParent p = new DisposableChild()) { } 

But something like this might break it:

 public class Program { public static void Main() { DisposableChild c = new DisposableChild(); DisposeOfIt(c); Console.ReadKey(true); } public static void DisposeOfIt(DisposableParent p) { p.Dispose(); } } 

Only prints that the parent has been deleted. Therefore, if you used this method, you need to be careful in managing the lifetime of your objects.

+3
source

All Articles