【问题标题】: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 语句,直到现在我才真正投入过多的思考。我总是发现异常,它从来没有让我真正担心过,但在阅读了这篇文章后,我意识到我错过了一些东西。

标签: c# exception try-catch using-statement


【解决方案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 失败

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-28
          • 1970-01-01
          • 1970-01-01
          • 2017-02-10
          • 2017-10-03
          • 2010-11-09
          • 2023-04-01
          相关资源
          最近更新 更多