Почему использование throw исключение, когда он должен вести себя как try / catch / finally? - PullRequest
1 голос
/ 06 марта 2012

Насколько я понимаю, использование работает как try / catch / finally, поэтому я ожидаю, что если в операторе using возникнет исключение, оно будет перехвачено (что довольно странно, поскольку это также означает, что исключениемолча едят).Оператор using должен перехватить исключение и вызвать метод Dispose, однако этого не происходит.Я разработал простой тест для демонстрации проблемы.

Вот где я вынуждаю исключение внутри оператора using:

using (TcpClient client = new TcpClient())
{
    // Why does this throw when the using statement is supposed to be a try/catch/finally?
    client.Connect(null);
}

Исключение - throw by client.Connect() (это означает, что он не был перехвачен оператором using или что он был переброшен):

System.ArgumentNullException: Value cannot be null.
Parameter name: remoteEP
   at System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
   at DotNETSandbox.Program.Main(String[] args) in C:\path\to\Sandbox\Program.cs:line 42

Согласно статье Microsoft по теме , оператор using может выдать, еслиDispose метод throws.

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

TcpClient c2 = new TcpClient();
try
{
    c2.Connect(null);               
}
catch (Exception e)
{
    // We caught the null ref exception
    try
    {
        // Try to dispose: works fine, does not throw!
        ((IDisposable)c2).Dispose();
    }
    catch (Exception e2)
    {
        Console.WriteLine(e2.ToString());
    }
    Console.WriteLine(e.ToString());
}

Я немного растерялся,так как я ожидал, что using будет вести себя как попытка / уловКто-нибудь может объяснить, почему это происходит?

Ответы [ 5 ]

8 голосов
/ 06 марта 2012

с использованием

try
{
}
finally
{
}

только !!!

нет подвоха!

в .net вам не нужно ловитьисключение ..

это просто механизм, который вызывает метод DISPOSE, как только вы покидаете область действия.вот и все.

ps: «как я узнаю, что мой объект можно использовать с помощью?»

ответ: не волнуйтесь - вы увидите ошибку во время компиляции.

5 голосов
/ 06 марта 2012

using больше try/finally без catch.

Элемент управления не может покинуть блок, если объект, который вы используете, не удаляется, вот и все .
Любое исключение, выброшенное изнутри блока, будет (после удаления) передаваться как обычно .

Edit: Выбор nits по моему собственному ответу, в особом случае реализации IEnumerable и выдачи из using можно сказать, что вы оставили блок без вызова Dispose (), но при продолжении перечисления вы ' Я снова окажусь внутри.

3 голосов
/ 06 марта 2012

Потому что using не ведет себя как try / catch / finally. Это ведет себя как попытка / наконец.

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

2 голосов
/ 06 марта 2012

Использование операторов ведет себя как блок try, finally, а не блок try, catch, finally.

Исключения будут по-прежнему выбрасываться из блока использования.

0 голосов
/ 06 марта 2012

Как многие говорили, оператор using не улавливает исключения. Но я вижу ваше замешательство из этой статьи.

В нем говорится, что IF Ошибка Dispose () может скрыть любые ошибки, которые были выданы в блоке using.

Поскольку Dispose () происходит внутри блока finally, ApplicationException никогда не будет виден вне блока using, если Dispose () терпит неудачу

...