Ответ 1
Да, Dispose
будет вызываться. Он вызвал, как только выполнение выходит из области using
, независимо от того, что означает, что нужно оставить блок, будь то завершение выполнения блока, оператор return
или исключение.
Как правильно указывает @Noldorin, использование блока using
в коде компилируется в try
/finally
, причем Dispose
вызывается в блоке finally
. Например, следующий код:
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
эффективно становится:
MemoryStream ms = new MemoryStream();
try
{
// code
return 0;
}
finally
{
ms.Dispose();
}
Итак, поскольку finally
гарантированно выполнится после завершения выполнения блока try
, независимо от его пути выполнения, Dispose
гарантированно будет вызываться, несмотря ни на что.
Для получения дополнительной информации см. эту статью MSDN.
Приложение:
Просто немного предостережения, чтобы добавить: потому что Dispose
гарантированно будет вызван, почти всегда хорошая идея гарантировать, что Dispose
никогда не выдает исключение при реализации IDisposable
. К сожалению, в основной библиотеке есть некоторые классы, которые вызывают определенные обстоятельства при вызове Dispose
- я смотрю на вас, справочник службы WCF/клиентский прокси! - и когда это произойдет, может быть очень сложно отследить исходное исключение, если вызов Dispose
был вызван во время стека исключений, поскольку исходное исключение проглатывается в пользу нового исключения, генерируемого вызовом Dispose
. Это может быть безумно расстраивающим. Или это расстраивает безумие? Один из двух. Возможно оба.