Reputation: 118
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
Upvotes: 5
Views: 1768
Reputation: 13638
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.
Upvotes: 0
Reputation: 499302
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
.
Upvotes: 3
Reputation: 6746
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.
Upvotes: 0