yanong_banikanhon
yanong_banikanhon

Reputation: 118

Casting to IDisposable before calling Dispose()

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

Answers (3)

Andrew T Finnell
Andrew T Finnell

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

Oded
Oded

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

JBSnorro
JBSnorro

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

Related Questions