当它应该表现得像 try/catch/finally 时,为啥使用会抛出异常?
Posted
技术标签:
【中文标题】当它应该表现得像 try/catch/finally 时,为啥使用会抛出异常?【英文标题】:Why does using throw an exception when it's supposed to behave like try/catch/finally?当它应该表现得像 try/catch/finally 时,为什么使用会抛出异常? 【发布时间】:2012-03-24 08:15:52 【问题描述】:据我了解,使用类似于 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语句可能会抛出。
但是,当我遵循 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。谁能解释为什么会这样?
【问题讨论】:
using 语句的行为类似于 try, finally 块,而不是 try catch finally。异常仍然会抛出 using 块。 为什么会发生what?您是否希望using
语句默默地吃掉异常?
@SLaks 出于某种原因,我留下的印象是using
有一个 catch 语句,直到现在我才真正投入过多的思考。我总是发现异常,它从来没有让我真正担心过,但在阅读了这篇文章后,我意识到我错过了一些东西。
【参考方案1】:
使用是
try
finally
仅限 !!!
没有问题!
在 .net 中,您不必捕获异常..
它只是一种在您离开作用域后立即调用 DISPOSE 方法的机制。就是这样。
附言:“我怎么知道我的对象是否可以与 using 一起使用?”
答案:别担心 - 你会在编译时看到错误。
【讨论】:
我明白了...好吧,现在说得通了! 另外,如果一个对象实现了IDisposable接口,你可以判断它是否可以使用using【参考方案2】:using
更像是一个try/finally
没有catch
。
如果您正在使用的对象没有被 Disposed,控件就无法离开块,就是这样。从块内部抛出的任何异常都将(在 Disposing 之后)照常传递.
编辑:在我自己的答案中挑选尼特,在实现 IEnumerable 并从using
中产生的特殊情况下,您可以说在没有调用 Dispose() 的情况下离开该块,但是在继续枚举时您'最终会再次回到里面。
【讨论】:
【参考方案3】:因为using
的行为不像 try/catch/finally。它的行为类似于 try/finally。
您的第一个示例虽然引发了异常,但仍将正确处理 TcpClient。
【讨论】:
【参考方案4】:Using 语句的行为类似于 try、finally 块,而不是 try、catch、finally 块。
异常仍然会从 using 块中抛出。
【讨论】:
【参考方案5】:正如许多人所说,using 语句不会捕获异常。但我可以从这篇文章中看出你的困惑。
它说 如果 Dispose() 失败,它可以隐藏在 using 块中引发的任何错误。
因为 Dispose() 发生在“finally”块内,如果 Dispose() 在 using 块外永远不会出现 ApplicationException 失败
【讨论】:
以上是关于当它应该表现得像 try/catch/finally 时,为啥使用会抛出异常?的主要内容,如果未能解决你的问题,请参考以下文章