Порядок удаления в C# с использованием блоков

Меня очень беспокоит необходимость вложения using блоков в С#. Это не элегантно и занимает много места. В некоторых случаях это кажется неизбежным, потому что мне нужно объявить переменные разных типов данных, но кажется, что случай с одним типом можно упростить. Под «однотипным случаем» я подразумеваю, когда несколько переменных одного типа объявляются последовательно. Вот пример того, о чем я говорю:

class Program
{
    static void Main(string[] args)
    {
        using (A a = new A("a"), b = new A("b"))
        {
        }
    }

    class A : IDisposable
    {
        string n = null;
        public A(string name)
        {
            n = name;
            Console.WriteLine(String.Format("Creating {0}", n));
        }

        public void Dispose()
        {
            Console.WriteLine(String.Format("Disposing {0}", n));
        }
    }
}

Я хочу, чтобы это работало так: a создается до b, а b размещается перед a. К сожалению, в спецификации C# нет никаких указаний относительно того, как это должно происходить на самом деле. Похоже, что компилятор Microsoft C# обрабатывает это так, поскольку это результат запуска вышеуказанной программы:

Creating a
Creating b
Disposing b
Disposing a

Однако у меня нет способа гарантировать, что это детерминированное поведение. Может ли кто-нибудь подтвердить или опровергнуть идею о детерминированности этой последовательности? Ссылки было бы здорово. И, очевидно, если он склонен к поломке (незадокументированный и т. д.), он, вероятно, бесполезен, но это полезно знать.

Уже есть аналогичный вопрос о детерминированном удалении, в котором говорится о случае с несколькими типами, и я понимаю, что здесь нет реального решения, кроме хитрых синтаксических трюков. В любом случае, большинство ответов там упускают суть. Мой вопрос касается случая с одним типом и того, является ли это удаление детерминированным и надежным или нет. Спасибо.


person Philip Hanson    schedule 10.08.2010    source источник
comment
Альтернатива хуже ИМХО   -  person    schedule 10.08.2010


Ответы (2)


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

«Оператор using в форме using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) в точности эквивалентен последовательности вложенных операторов using

using (ResourceType r1 = e1)
   using (ResourceType r2 = e2)
      ...
         using (ResourceType rN = eN)
            statement

Таким образом, кажется справедливым сказать, что это совершенно незыблемо.

person mqp    schedule 10.08.2010
comment
Круто, это именно то, что мне нужно было знать. Из какого это раздела, кстати? И какая версия спец. Я выполнил полнотекстовый поиск спецификации С# 4.0 и все равно пропустил его. - person Philip Hanson; 11.08.2010
comment
Я связался с точным разделом: X msdn.microsoft .com/en-us/library/aa664736(v=VS.71).aspx - person mqp; 12.08.2010

Есть ли какая-то причина, по которой вы не можете использовать трюк с множественным использованием? Это полностью детерминировано и решает вашу проблему

using (A a = new A("a"))
using (A b = new A("b")) {
    // ....
}
person thecoop    schedule 10.08.2010
comment
Мне не нравится использовать этот синтаксис по той же причине, по которой я не люблю использовать операторы if без фигурных скобок. Он работает, и я им пользуюсь, но всегда боюсь, что сломаю его при дальнейшем обслуживании. Для смешанных типов данных это единственный вариант, но было бы неплохо иметь более чистый детерминированный синтаксис. - person Philip Hanson; 11.08.2010