据我所知,使用像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
根据a Microsoft article on the topic,如果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
表现得像try / catch。有人可以解释为什么会这样吗?
答案 0 :(得分:8)
使用是
try
{
}
finally
{
}
仅 !!!
没有捕获!
<。>在.net中你不必抓住异常..它只是一个在离开范围时调用DISPOSE方法的机制。多数民众赞成。
P.S。 :“我怎么知道我的对象是否可以用于使用?”
回答:别担心 - 你会在编译时看到错误。
答案 1 :(得分:5)
using
更多的是try/finally
而不是catch
。
如果没有你正在使用的对象,则控件不能离开块,就是。从块内部抛出的任何异常都将(在Disposing之后)传递给正常。
编辑:在我自己的答案中挑选尼特,在实现IEnumerable和从using
中产生的特殊情况下,你可以说在没有调用Dispose()的情况下离开块,但在继续枚举时你最终会重新回到里面。
答案 2 :(得分:3)
因为using
的行为不像try / catch / finally。它的行为类似于try / finally。
你的第一个例子,当它抛出异常时,仍然可以正确地处理TcpClient。
答案 3 :(得分:2)
使用语句的行为类似于try,finally块,而不是try,catch,finally块。
异常仍然会抛弃使用块。
答案 4 :(得分:0)
正如许多人所说,使用声明不会捕获异常。但我可以从这篇文章中看出你的困惑。
它表示 IF Dispose()失败,它可以隐藏在使用块中抛出的任何错误。
因为 Dispose()发生在“finally”块内,如果 Dispose(),则在使用块之外永远不会看到 ApplicationException 失败