Приведение к IDisposable перед вызовом Dispose () - PullRequest
4 голосов
/ 13 августа 2011

В чем причина приведения к IDisposable перед вызовом 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;
     }
}

Это одна из конкретных реализаций 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;
         }
      }

}

Я много раз видел этот фрагмент кода в реализации шаблона репозитория с открытым исходным кодом, и я не могу понять причину приведения. Прямой вызов транзакции. Dispose () внутри , если предложение должно работать нормально. Я что-то пропустил?

Оригинальный код можно найти здесь: NHibernateTransaction.cs

Ответы [ 3 ]

3 голосов
/ 13 августа 2011

Поскольку ITransaction наследуется от IDisposable, возможно, разработчик реализовал IDisposable в качестве явной реализации интерфейса , и в этом случае приведение требуется для доступа к реализованным элементам.

В таком случае приведение гарантирует, что вызов вызовет метод IDisposable.Dispose.Приведение выполнено, чтобы охватить все базы.

Если ITransaction не наследуется от IDisposable, но реализует его, то для вызова Dispose требуется приведение.В таком случае может произойти сбой (исключение), если средство реализации не реализует IDisposable.

0 голосов
/ 13 августа 2011

Я делаю это не часто, но я ударил весь свой первоначальный ответ, так как понимаю, что сейчас пытается сказать Одед.Их цель - решить эту проблему:

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

Что вызывает транзакция.Он вызывает IDisposable.Dispose()

Проблема, однако, заключается в том, что, поскольку контракт в EndTransaction является ITransaction, он всегда будет вызывать версию IDisposable.

0 голосов
/ 13 августа 2011

При вызове Dipose() на интерфейсе, производном от IDisposable, нет никакой разницы.

Может быть разница при вызове Dispose() для класса, реализующего IDisposable, потому что метод Dispose()может быть реализовано явно.

...