Почему использование вызывает исключение, если оно должно вести себя как try / catch / finally?

Насколько я понимаю, using работает как 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);
}

Исключение генерируется 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 выбрасывает.

Однако, когда я следую шаблону using, очевидно, что метод 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 будет вести себя как попытка / улов. Может ли кто-нибудь объяснить, почему это происходит?


person Kiril    schedule 06.03.2012    source источник
comment
Операторы using ведут себя как блок try, finally, а не как try catch finally. Исключения все равно будут выбрасываться из блока using.   -  person Stefan H    schedule 06.03.2012
comment
Почему что происходит? Ожидаете ли вы, что оператор using молча ест исключения?   -  person SLaks    schedule 06.03.2012
comment
@SLaks по какой-то причине у меня сложилось впечатление, что using имеет оператор catch, и до сих пор я никогда особо не думал об этом. Я всегда ловил исключения, и меня это никогда особо не волновало, но после прочтения статьи я понял, что чего-то не хватает.   -  person Kiril    schedule 06.03.2012


Ответы (5)


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

try
{
}
finally
{
}

только !!!

нет никакого подвоха!

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

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

p.s. : "как я узнаю, можно ли использовать мой объект с помощью using?"

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

person Royi Namir    schedule 06.03.2012
comment
Понятно ... Хорошо, теперь это имеет смысл! - person Kiril; 06.03.2012
comment
Кроме того, вы можете определить, может ли объект использовать using, если он реализует интерфейс IDisposable. - person Stefan H; 06.03.2012

using больше похож на try/finally без catch.

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

Изменить: выбор гнид в моем собственном ответе, в особом случае реализации IEnumerable и выхода из using можно сказать, что вы оставите блок без вызова Dispose (), но при продолжении перечисления вы вернетесь обратно снова внутри.

person Joachim Isaksson    schedule 06.03.2012

Потому что using не ведет себя как попытка / поймать / наконец. Он ведет себя как попытка / наконец.

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

person Justin Niessner    schedule 06.03.2012

Операторы using ведут себя как блок try, finally, а не блок try, catch, finally.

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

person Stefan H    schedule 06.03.2012

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

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

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

person nickles80    schedule 06.03.2012