为什么使用会在';我们应该表现得像try/catch/finally

本文关键字:try finally catch 我们 为什么 | 更新日期: 2023-09-27 18:27:01

据我所知,using的工作方式类似于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

根据微软关于该主题的一篇文章,如果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。有人能解释为什么会发生这种事吗?

为什么使用会在';我们应该表现得像try/catch/finally

使用is

try
{
}
finally
{
}

!!!

没有陷阱!

在.net中,你不必抓住例外。。

它只是一种在您离开作用域时立即调用DISPOSE方法的机制。仅此而已。

p.s.:"我怎么知道我的物体是否可以和使用一起使用?"

答案:别担心,编译时会出现错误。

using更像是一个没有catchtry/finally

控件不能在没有处理您正在使用的对象的情况下离开块,仅此而已
从块内部抛出的任何异常都将(在Disposang之后)正常传递。

编辑:根据我自己的答案,在实现IEnumerable并从using中让步的特殊情况下,可以说你在没有调用Dispose()的情况下离开了块,但当继续枚举时,你会再次回到块内。

因为using的行为不像try/catch/finally。它表现得像是一次尝试。

第一个例子在抛出Exception时,仍然会正确地处置TcpClient。

Using语句的行为类似于try,finally块,而不是try,catch,finally阻塞。

异常仍然会抛出using块。

正如许多人所说,using语句不会捕获异常。但我从这篇文章中可以看出你的困惑。

它说如果Dispose()失败,它可以隐藏在using块中抛出的任何错误。

因为Dispose()发生在"finally"块内,所以如果Dispose()失败

,则在使用块外永远看不到ApplicationException