Co się stanie, jeśli wrócę przed zakończeniem korzystania z instrukcji? Czy dyspozycja zostanie wywołana?

Mam następujący kod

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

Metoda dispose() jest wywoływana na końcu using wyrażenia } prawda? Skoro I return przed zakończeniem using, czy obiekt MemoryStream będzie prawidłowo usuwany? Co tu się dzieje?

Author: George Stocker, 2010-07-14

5 answers

Tak, Dispose zostanie wywołany. Jest wywoływany, gdy tylko wykonanie opuści zakres bloku using, niezależnie od tego, jakie środki trzeba było opuścić blok, czy to koniec wykonania bloku, Instrukcja return, czy wyjątek.

Jak słusznie zauważył @Noldorin, użycie using bloku w kodzie jest kompilowane do try/finally, z wywołaniem Dispose w bloku finally. Na przykład następujący kod:

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

Skutecznie staje się:

MemoryStream ms = new MemoryStream();
try
{
    // code
    return 0;
}
finally
{
    ms.Dispose();
}

Więc, ponieważ finally jest gwarantowane wykonanie po zakończeniu wykonywania bloku try, niezależnie od jego ścieżki wykonania, Dispose jest gwarantowane wywołanie, bez względu na wszystko.

Aby uzyskać więcej informacji, zobacz Ten artykuł MSDN .

dodatek:
Małe zastrzeżenie do dodania: ponieważ Dispose jest gwarantowane wywołanie, prawie zawsze dobrym pomysłem jest upewnienie się, że Dispose nigdy nie wyrzuca wyjątku podczas implementacji IDisposable. Niestety, są zajęcia w biblioteka bazowa, która robi wrzuca w pewnych okolicznościach, gdy Dispose jest wywołana -- patrzę na Ciebie, WCF Service Reference / Client Proxy! -- i wtedy może być bardzo trudno wyśledzić oryginalny wyjątek, jeśli {[2] } został wywołany podczas odwijania stosu wyjątków, ponieważ oryginalny wyjątek zostaje połknięty na rzecz nowego wyjątku wygenerowanego przez wywołanie Dispose. To może być szalenie frustrujące. Czy to frustrujące? Jeden z dwóch. Może jedno i drugie.

 170
Author: Randolpho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-14 15:33:44

using instrukcje zachowują się dokładnie jak bloki try ... finally, więc zawsze będą wykonywane na dowolnych ścieżkach wyjścia kodu. Uważam jednak, że są one przedmiotem bardzo niewielu i rzadkich sytuacji, w których finally bloki nie są wywoływane. Jednym z przykładów, który pamiętam, jest to, czy wątek pierwszoplanowy kończy się, gdy wątki tła są aktywne: wszystkie wątki oprócz GC są wstrzymane, co oznacza, że finally bloki nie są uruchamiane.

Oczywisty edit: zachowują się tak samo poza logiką, która pozwala im obsługiwać IDisposable objects, d ' Oh.

Zawartość bonusowa: mogą być ułożone w stos (gdzie typy się różnią):

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

}

Oraz rozdzielane przecinkami (gdzie typy są takie same):

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

}
 19
Author: Adam Houldsworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-24 21:42:24

Twój obiekt MemoryStream zostanie usunięty prawidłowo, nie musisz się o to martwić.

 4
Author: Otávio Décio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-14 15:17:23
 3
Author: RSolberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-14 15:17:49

Spójrz na swój kod w reflector po skompilowaniu go. Przekonasz się, że kompilator refakturuje kod, aby upewnić się, że dispose jest wywoływany w strumieniu.

 0
Author: Wil P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-14 15:18:21