Given the following class which implements both Dispose and IDisposable.Dispose:
internal class DisposableClass : IDisposable
{
public void Dispose()
{
}
void IDisposable.Dispose()
{
}
}
When I make a call to DisposeableClass.Dispose (through an instance of the class), the public void Dispose is called:
DisposableClass newClass = new DisposableClass();
try
{
}
finally
{
newClass.Dispose();
}
If you change the try-finally to a using statement, IDisposable.Dispose is called.
using (DisposableClass newClass = new DisposableClass())
{
}
But NOT the IDisposable.Dispose which I defined.
The compiler translates the using-statement to ((IDisposable)newClass).Dispose(). The full methodname shows it to be from System.IDisposable.Dispose.
IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose()
When will my custom implementation of IDisposable.Dispose be called?
Note that I am not using this actual implementation and I get that this should not be used. But I am still curious as to which implementation gets called when.
If I'd have a different implementation for each of the Dispose methods; which implementation would be called when?
Your approach to disposing is wrong. You should look at The Dispose Pattern to understand how to do this properly.
However... To answer your question how / why are they called...
Your public void Dispose() is being called when you say newClass.Dispose(); because it is the best "match" for what you have asked. By that (and without getting too complicated) it is because it is the highest in the hierarchy and therefore the one the compiler expects you to mean because it is the most specific. If you hadn't created your own it would have gone through hierarchy to find a Dispose method.
When you wrap with using the compiler produces code similar to this:
DisposableClass newClass = new DisposableClass();
try
{
}
finally
{
((IDisposable)newClass).Dispose();
}
This will therefore call the IDiposable version explicitly.
UPDATE
Full working sample below that will give this output:
Manually calling newClass.Dispose();
public void Dispose() being called.
Now wrapped in using...
void IDisposable.Dispose() being called.
Manually calling IDisposable.Dispose();
void IDisposable.Dispose() being called.
Full working code (paste this inside a console app and run):
using System;
namespace zPlayGround
{
class Program
{
static void Main()
{
Console.WriteLine("Manually calling newClass.Dispose();");
var newClass = new DisposableClass();
try
{
}
finally
{
newClass.Dispose();
}
Console.WriteLine("Now wrapped in using...");
using (var usingClass = new DisposableClass())
{
}
Console.WriteLine("Manually calling IDisposable.Dispose();");
var demoClass = new DisposableClass();
try
{
}
finally
{
((IDisposable)newClass).Dispose();
}
Console.ReadKey();
}
}
internal class DisposableClass : IDisposable
{
public void Dispose()
{
Console.WriteLine("public void Dispose() being called.\r\n");
}
void IDisposable.Dispose()
{
Console.WriteLine("void IDisposable.Dispose() being called.\r\n");
}
}
}
Related
Is there a .NET class which calls a method when it gets disposed, sometimes instead of:
try
{
...
}
finally
{
MyCleanupMethod()
}
I'd like to:
using(new OnDisposed(MyCleanupMethod))
{
...
}
Before I get berated, for three reasons:
For long try blocks it allows the reader to see what needs to be cleaned up at the start
try has an implication that its catching an error (which it's not)
To keep the disposal code private (if the IDisposable object is returned from a class)
Is this valid practice? If so, is a .NET class which does this?
You could add a constructor that takes the action:
public class OnDisposed : IDisposable
{
private readonly Action _disposeAction;
public OnDisposed(Action disposeAction)
{
_disposeAction = disposeAction;
}
public void Dispose()
{
// ...
if(_disposeAction != null)
_disposeAction();
}
}
For example:
using (new OnDisposed(() => Console.WriteLine("Dispose Called")))
{
Console.WriteLine("In using...");
}
Is it dangerous to use a memorystream as a private field in an instance class?
The class implements IDisposable:
class MyIDisposableClass:IDisposable{
private MemoryStream _stream;
//do stuff with _stream
void Dispose(){
_stream.Close();
_stream.Dispose();//does this statement make sense here ?
}
}
and will be used like this:
using(MyIDisposableClass() bla=new MyIDisposableClass())
{...}
Is that good approach or should I do something else, to give all class member access to that kind of information?
You're fine as long as you are wrapping your object in a using
After the using block the object's disposed method will get called. As long as you clean up everything you'll be fine.
And if you are worried about when it will be called the code here will show you.
using System;
public class DisposableExample : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposed");
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Before Disposing");
using(var disposableObj = new DisposableExample())
{
Console.WriteLine("Inside Using Statement");
}
Console.WriteLine("After Disposing");
}
}
This will print out
Before Disposing
Inside Using Statement
Disposed
After Disposing
See fiddle here
I work on a huge project in C# .NET 4.0. There is a custom 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 content of CleanUp() method to Dispose(bool) method.
As first, I checked the source code of the base class - SocketAsyncEventArgs (using Go To Definition so that I saw metadata as source). I found out, this class implements IDisposable interface. Nice, I just need to override the Dispose(bool) method, don't I? (See IDisposable Interface on MSDN, the "IDisposable and the inheritance hierarchy" section, for more details). Nothing new for me... Unfortunately, the SocketAsyncEventArgs class is implemented as following:
public class SocketAsyncEventArgs : EventArgs, IDisposable
{
public void Dispose();
//some other stuff here
}
That means, there is no way how to override Dispose(bool) method, as it's implemented as private instead of protected... What is the reason for this?
Next, I read about SocketAsyncEventArgs.Dispose() method on MSDN. The funny thing is that, it contains the following section:
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.
Wait... what?
When overriding Dispose(Boolean), ...
How am I supposed to override Dispose(Boolean)?
What is the recommended way to implement IDisposable interface in this case?
There doesn't seem to be anything stopping you from implementing IDisposable on 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 was disposed.
The child was disposed.
The compiler warns about hiding the dispose of the parent class in the child, so using the new operator gets rid of that warning, just make sure to call the base class Dispose from the child class (and implement it the right way).
The dispose for the child would 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 still works if you do something like:
using (DisposableParent p = new DisposableChild())
{
}
But something like this can 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 out that the parent was disposed. So if you used this method you would have to be careful about controlling the lifetime of your objects.
I'm coding in C# and I created a class that I would like to use in a 'using' block.
Is this possible and if so, how should I proceed and what to I need to add to my class?
The using keyword can be used on any object that implements IDisposable. To implement IDisposable, include a Dispose method in your class.
It's usually important to also include the Dispose functionality in your class's finalizer in case users of your library don't (or forget to) call Dispose.
For example:
class Email : IDisposable {
// The only method defined for the 'IDisposable' contract is 'Dispose'.
public void Dispose() {
// The 'Dispose' method should clean up any unmanaged resources
// that your class uses.
}
~Email() {
// You should also clean up unmanaged resources here, in the finalizer,
// in case users of your library don't call 'Dispose'.
}
}
void Main() {
// The 'using' block can be used with instances of any class that implements
// 'IDisposable'.
using (var email = new Email()) {
}
}
public class MyClass : IDisposable
{
public void Dispose()
{
}
}
That's all there is to it! In calling code you'd be able to do the following:
using(var mc = new MyClass())
{
}
What is the reason of casting to IDisposable before calling Dispose() ?
public interface ITransaction : IDisposable
{}
.
.
.
//in some other class:
public void EndTransaction(ITransaction transaction)
{
if (transaction != null)
{
(transaction as IDisposable).Dispose();
// is the following code wrong? transaction.Dispose()
transaction = null;
}
}
This is one of the concrete implementation of ITransaction:
public class NHibernateTransaction : ITransaction
{
public NHibernateTransaction(NHibernate.ITransaction transaction)
{
this.Transaction = transaction;
}
protected NHibernate.ITransaction Transaction { get; private set; }
public void Dispose()
{
if ( this.Transaction != null )
{
(this.Transaction as IDisposable).Dispose(); // this is NHibernate ITransaction object
this.Transaction = null;
}
}
}
I have seen that code snippet many times in an open source implementation of the repository pattern and I cannot seem to understand the reason behind the cast. Directly calling transaction.Dispose() inside the if clause should work just fine. Did I miss something?
The original code can be found here:
NHibernateTransaction.cs
Since ITransaction inherits from IDisposable, it is possible that the implementer has implemented IDisposable as an explicit interface implementation, in which case the cast is required in order to access the implemented members.
In such a case, casting ensures that the call will call the IDisposable.Dispose method. The cast is done to cover all bases.
If ITransaction doesn't inherit from IDisposable, but the implementer does, a cast is needed for Dispose to be callable. Such a case may fail (throwing an exception) if the implementer does not implement IDisposable.
When calling Dipose() on an interface deriving from IDisposable, there is no difference.
There could be a difference when calling Dispose() on a class implementing IDisposable, because the method Dispose() may be implemented explicitly.
I don't do this often but I whacked my whole original answer as I understand what Oded is trying to say now. Their intent is to solve this problem:
namespace StackOverflow7051864
{
using System;
public interface ITransaction : IDisposable {}
public interface ITryToConfuseDispose
{
void Dispose();
}
public class Transaction : ITransaction, ITryToConfuseDispose
{
void IDisposable.Dispose()
{
Console.WriteLine("Happy");
}
void ITryToConfuseDispose.Dispose()
{
Console.WriteLine("Confused");
}
}
class Program
{
static void Main(string[] args)
{
EndTransaction(new Transaction());
}
public static void EndTransaction(ITransaction transaction)
{
(transaction as IDisposable).Dispose();
transaction.Dispose();
}
}
}
What does 'transaction.Dispose()' invoke? It invokes IDisposable.Dispose()
The problem though, is that since the contract into EndTransaction is ITransaction, it will always invoke the IDisposable version.