2012-03-06 2 views
1

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

Вот где я заставляю исключение происходит внутри с помощью заявления:

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() (что означает, что он не был пойман с помощью заявления или что он был вновь брошен) :

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 

Согласно a Microsoft article on the topic, использование оператор может бросить, если метод Dispose бросков.

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

+3

с помощью заявления ведут себя как попытки, наконец, блок, а не попытка поймать наконец. Исключения будут выходить из блока использования. –

+3

Почему _what_ происходит? Ожидаете ли вы, что выражение 'use' должно содержать исключения? – SLaks

+0

@SLaks почему-то у меня сложилось впечатление, что 'using' имеет инструкцию catch, и я до сих пор не слишком много думал об этом. Я всегда ловил исключения, и меня это никогда не беспокоило, но, прочитав статью, я понял, что чего-то не хватает. – Kiril

ответ

8

используя это

try 
{ 
} 
finally 
{ 
} 

только !!!

нет обломок!

в .net вы не должны поймать исключение ..

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

p.s. : «Как я могу узнать, может ли мой объект использоваться с использованием?»

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

+0

Я вижу ... Хорошо, это имеет смысл сейчас! – Kiril

+0

Кроме того, вы можете узнать, может ли объект использовать, если он реализует интерфейс IDisposable –

5

using является более try/finally без catch.

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

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

3

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

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

2

Использование утверждений ведет себя как попытка, наконец, блок, а не попытка, catch, наконец-то блок.

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

0

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

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

Поскольку Dispose() происходит внутри «наконец,» блок, то ApplicationException никогда не видел снаружи с помощью блока, если Dispose() терпит неудачу