конструкция «использование» и обработка исключений

Конструкция «с использованием » выглядит невероятно удобной для ситуаций, когда требуются как начальная, так и разделенная конечная части.

Быстрый пример для иллюстрации:

using (new Tag("body")) {
    Trace.WriteLine("hello!");
}
//...
class Tag : IDisposable {
    String name;
    public Tag(String name) {
        this.name = name;
        Trace.WriteLine("<" + this.name + ">");
        Trace.Indent();
    }
    public void Dispose() {
        Trace.Unindent();
        Trace.WriteLine("</" + this.name + ">")
    }
}

Начальная часть определяется как конструктор, конечная часть — это метод Dispose.

Однако, несмотря на свою привлекательность, эта конструкция имеет серьезную оговорку, связанную с тем, что метод Dispose вызывается из блока finally. Итак, есть 2 проблемы:

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

  2. Внутри метода Dispose нет способа узнать, было ли ранее вызвано исключение между «началом» и «концом», и, следовательно, нет способа соответствующим образом обработать «конечную» часть.

Эти 2 вещи делают использование этой конструкции непрактичным, что является очень печальным фактом. Теперь мои вопросы:

  1. Правильно ли я понимаю проблемы? Это то, как на самом деле работает «использование»?

  2. Если да, то есть ли способ преодолеть эти проблемы и найти практическое применение конструкции «использования», отличной от того, для чего она изначально была предназначена (для высвобождения ресурсов и очистки)

  3. В случае, если нет практического способа использования «использования» таким образом. Каковы альтернативные подходы (для принудительного применения контекста к некоторому коду с начальной и конечной частями )?

13
задан Trident D'Gao 30 June 2012 в 01:04
поделиться