Reputation: 40345
As far as I understand, using works like a try/catch/finally, so I would expect that if an exception occurs in a using statement it would get caught (which is kinda odd, because that would also mean that the exception is silently eaten). The using statement should catch the exception and call the Dispose
method, however, that is not happening. I've devised a simple test to demonstrate the issue.
Here is where I force an exception to occur inside the using statement:
using (TcpClient client = new TcpClient())
{
// Why does this throw when the using statement is supposed to be a try/catch/finally?
client.Connect(null);
}
An exception is throw by client.Connect()
(meaning that it was not caught by the using statement or that it was re-thrown):
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
According to a Microsoft article on the topic, the using statement might throw if the Dispose
method throws.
However, when I'm following the using pattern, it is evident that the Dispose method does not throw:
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());
}
I'm a little confused, since I was expecting using
to behave like a try/catch. Could anybody explain why this is happening?
Upvotes: 1
Views: 1433
Reputation: 1101
As many people have said the using statement does not catch exceptions. But I can see your confusion from this article.
It says that IF the Dispose() fails it can hide any errors that were thrown within the using block.
Because the Dispose() occurs inside a "finally" block, the ApplicationException is never seen outside the using block if the Dispose() fails
Upvotes: 0
Reputation: 148524
using is
try
{
}
finally
{
}
only !!!
there is no catch !
in .net you dont have to catch the exception..
its just a mechanism which calls DISPOSE method as soon as you leave the scope . thats all.
p.s. : " how will i know if my object can be used with using ?"
answer : don't worry - you will see error on compile time.
Upvotes: 8
Reputation: 180917
using
is more of a try/finally
without a catch
.
Control can't leave the block without the object you're using being Disposed, that's it.
Any exception thrown from inside the block will (after Disposing) be passed on as normal.
Edit: Picking nits on my own answer, in the special case of implementing an IEnumerable and yielding out of a using
you could be said to leave the block without Dispose() being called, but when continuing the enumeration you'll end up right back inside again.
Upvotes: 5
Reputation: 6683
Using statements behave like a try, finally block, not a try, catch, finally block.
Exceptions will still throw out of the using block.
Upvotes: 2
Reputation: 245429
Because using
doesn't behave like a try/catch/finally. It behaves like a try/finally.
Your first example, while it throws an Exception, will still properly Dispose the TcpClient.
Upvotes: 3