У меня есть следующий код
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
dispose()
Метод вызывается в конце using
заявления брекет }
правильно? Так как I return
до конца using
оператора, будет ли MemoryStream
объект размещен должным образом? Что здесь происходит?
Ответы:
Да,
Dispose
назовут. Он вызывается, как только выполнение покидает область действияusing
блока, независимо от того, какие средства потребовались для выхода из блока, будь то конец выполнения блока,return
инструкция или исключение.Как правильно указывает @Noldorin, использование
using
блока в коде компилируется вtry
/finally
с вызовомDispose
вfinally
блоке. Например, следующий код:фактически становится:
Таким образом, поскольку
finally
он гарантированно выполняется послеtry
завершения выполнения блока, независимо от его пути выполнения,Dispose
он гарантированно будет вызван, несмотря ни на что.Дополнительные сведения см. В этой статье MSDN .
Дополнение:
небольшая оговорка, которую следует добавить: поскольку
Dispose
вызывается гарантированно, почти всегда полезно убедиться, чтоDispose
при реализации никогда не будет генерироваться исключениеIDisposable
. К сожалению, есть некоторые классы в библиотеке ядра , которые делают бросок в определенных обстоятельствах , когдаDispose
называются - я смотрю на вас, WCF Service Reference / Client Proxy! - и когда это происходит, может быть очень сложно отследить исходное исключение, если оноDispose
было вызвано во время раскрутки стека исключений, поскольку исходное исключение поглощается в пользу нового исключения, сгенерированногоDispose
вызовом. Это может быть безумно неприятным. Или это ужасно сводит с ума? Один из двух. Возможно оба.источник
Dispose
in finally, так что он эффективно отрабатывает реализациюfinally
, как вы описываете.using
операторы ведут себя точно так же, какtry ... finally
блоки, поэтому всегда будут выполняться на любом пути выхода кода. Однако я считаю, что они подвержены очень немногим и редким ситуациям, в которыхfinally
блоки не вызываются. Я могу вспомнить один пример: если поток переднего плана завершается, когда фоновые потоки активны: все потоки, кроме GC, приостановлены, то естьfinally
блоки не запускаются.Очевидное изменение: они ведут себя одинаково, за исключением логики, которая позволяет им обрабатывать IDisposable объекты, d'oh.
Бонусный контент: их можно складывать друг в друга (если типы различаются):
А также через запятую (где типы совпадают):
источник
Ваш объект MemoryStream будет правильно удален, не о чем беспокоиться.
источник
С этим
using
оператором объект будет удален независимо от пути завершения.Дальнейшее чтение...
источник
Взгляните на свой код в отражателе после его компиляции. Вы обнаружите, что компилятор реорганизует код, чтобы гарантировать, что dispose вызывается в потоке.
источник