当它应该表现得像 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 时,为啥使用会抛出异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 Material UI 图标表现得像锚标签?

htmx:如何使每一行表现得像一个表格?

是啥让 UITableView 表现得像这样

让 div 表现得像 iframe

使 UIScrollView 表现得像 UIPageControl

如何使 Recycler View 表现得像 PlayStore Recycler Views