Что делает использование инструкции без переменной при утилизации?

Я всегда использовал использование с переменной и присваиванием. Теперь у меня есть класс DbProviderConnection класса:

public class DbProviderConnection : IDisposable
{
    public DbConnection Connection { get; set; }
    public DbTransaction Transaction { get; set; }

    public DbTransaction BeginTransaction()
    {
        Transaction = Connection.BeginTransaction();
        return Transaction;
    } 

    //... and so on
}

Теперь я подумал, чтобы использовать его вот так:

using (DbProviderConnection cnctn = _planDb.CreateOpenConnection())
{
    using (cnctn.BeginTransaction())
    {
        //...
        cnctn.Transaction.Commit();
    }
}

Мой вопрос: вызывается ли DbProviderConnection.Transaction.Dispose?

Ответы

Ответ 1

Из С# Specification 8.13 с использованием оператора, определенного как

using-statement:
   using (resource-acquisition) embedded-statement

Если получение ресурсов

resource-acquisition:
    local-variable-declaration
    expression

В первом случае вы используете, который приобретает ресурс через объявление локальной переменной. Во втором случае ресурс приобретается через выражение. Итак, во втором случае resouce будет результатом вызова cnctn.BeginTransaction(), который DbTransaction из вашего класса DbProviderConnection. Использование выражения предоставляет свой ресурс после использования. Итак, да, DbProviderConnection.Transaction.Dispose() будет вызван.

ОБНОВЛЕНИЕ: согласно той же статье ваш второй блок использования будет переведен на

DbTransaction resource = cnctn.BeginTransaction();
try
{
    //...
    cnctn.Transaction.Commit();
}
finally 
{
   if (resource != null) 
      ((IDisposable)resource).Dispose();
}

Ответ 2

Да, Dispose будет вызван. Оператор tTe using работает только с одноразовыми объектами. Вот так:

using (DbProviderConnection cnctn = _planDb.CreateOpenConnection())
{
    using (cnctn.BeginTransaction())
    {
        //...
        cnctn.Transaction.Commit();
    } //HERE THE BEGIN TRANSACTION DISPOSE() METHOD IS BE CALLED.
}//HERE THE DbProviderConnection  DISPOSE() METHOD IS BE CALLED.

Ответ 3

Из спецификации:

8.13 Оператор using

A, используя инструкцию вида

using (ResourceType resource = expression) statement

когда ResourceType является типом значения NULL или ссылочным типом, отличным от динамического, расширение

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        if (resource != null) ((IDisposable)resource).Dispose();
    }
}

A, используя инструкцию вида

using (expression) statement

имеет те же три возможных разложения... Переменная ресурса недоступна и невидима для встроенного оператора.

Поэтому объект, возвращенный из cnctn.BeginTransaction(), будет удален, когда блок выйдет, но недоступен внутри соответствующего блока.

Ответ 4

Объект, возвращаемый BeginTransaction, является тем, что будет удалено.

BeginTransaction возвращает DbTransaction, так что это будет размещено