Что происходит, если я возвращаюсь до конца использования оператора? Расположение назовут?

У меня есть следующий код

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}

dispose() в конце метода называют using фигурные скобки оператора } правильно? Так как я return до конца using оператор, будет MemoryStream возразить быть расположенными правильно? Что происходит здесь?

112
задан George Stocker 14 July 2010 в 15:19
поделиться

5 ответов

Да, 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 Service Reference / Client Proxy! -- и когда это происходит, может быть очень трудно отследить исходное исключение, если Dispose был вызван во время разворачивания стека исключений, поскольку исходное исключение будет проглочено в пользу нового исключения, сгенерированного вызовом Dispose. Это может быть безумно неприятно. Или это расстраивает? Одно из двух. Возможно, и то, и другое.

162
ответ дан 24 November 2019 в 02:51
поделиться
Операторы

using ведут себя точно так же, как блоки try ... finally , поэтому всегда будут выполняться на любых путях выхода кода. Однако я считаю, что они подвержены очень немногим и редким ситуациям, в которых блоки finally не вызываются. Я могу вспомнить один пример: если поток переднего плана завершается, когда фоновые потоки активны: все потоки, кроме GC, приостанавливаются, то есть блоки , наконец, не запускаются.

Очевидное изменение: они ведут себя одинаково, за исключением логики, которая позволяет им обрабатывать IDisposable объекты, ооо.

Дополнительный контент: их можно складывать друг в друга (если типы различаются):

using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{

}

А также с разделителями-запятыми (где типы совпадают):

using (SqlCommand comm = new SqlCommand("", conn), 
       SqlCommand comm2 = new SqlCommand("", conn))
{

}
18
ответ дан 24 November 2019 в 02:51
поделиться

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

4
ответ дан 24 November 2019 в 02:51
поделиться

С помощью оператора using объект будет утилизирован независимо от пути завершения.

Дальнейшее чтение...

3
ответ дан 24 November 2019 в 02:51
поделиться

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

0
ответ дан 24 November 2019 в 02:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: