为什么当它应该像try / catch / finally一样使用时抛出异常?

时间:2012-03-06 19:42:51

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

据我所知,使用像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。有人可以解释为什么会这样吗?

5 个答案:

答案 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 失败