使用try catch语句块与using语句块。使用语句块中的实例会发生什么?

9
如果我使用一个using块包含一个try catch语句,假设catch捕获了异常,那么在该using语句块内的对象会发生什么?请考虑以下代码:
using (IDatabaseConnectivityObject databaseConnectivityObject = new DbProviderFactoryConnectionBasicResponse())
{
    try
    {
        Foo();
    }
    catch (ArgumentNullException e)
    {
        throw;
    }
}

如果我们假设Foo()失败并触发了异常并有效地使程序崩溃,那么databaseConnectivityObject会被处理吗?这很重要的原因是该对象有一个与之关联的数据库连接。
5个回答

12

你可以将 using 视为 try-finally 的简写形式。因此,你的代码等同于:

IDatabaseConnectivityObject databaseConnectivityObject = new DbProviderFactoryConnectionBasicResponse();
try
{
    try
    {
        Foo();
    }
    catch(ArgumentNullException e)
    {
        throw;
    }
}
finally
{
  if(databaseConnectivityObject != null)//this test is often optimised away
    databaseConnectivityObject.Dispose()
}

从这个角度看,你可以看出如果抛出异常,Dispose()确实会被调用,因为try-finally在try-catch之外。

这正是我们使用using的原因。


7
我们假设Foo()失败并抛出异常并有效地使程序中断,那么databaseConnectivityObject会被处理吗?
是的,它将被处理。using在内部使用try-finally(仅适用于实现IDisposable的对象) 来自MSDN-使用语句 using语句确保调用对象的方法时即使发生异常,也会调用Dispose。您可以通过将对象放置在try块中,然后在finally块中调用Dispose来实现相同的结果;实际上,这就是编译器如何将using语句转换的方式。

因此,实际上 using 语句是在尝试使用块中的所有代码,并在我们看不到的 finally 块中最终调用 MyObject.Dispose() 吗? - CSharpened
1
@CSharpened,完全正确,就是这样。您可以在答案中的链接上看到更详细的示例。 - Habib

3
是的,您的using块会释放数据库连接对象,无论您是否有try-catch块。
您说使用using块很重要,应该为所有实现IDisposable接口的类使用它,以确保即使出现异常情况也能正确地释放它们。
来自MSDN-using语句 using语句确保在调用对象上的方法时即使发生异常也会调用Dispose。您可以通过将对象放入try块中并在finally块中调用Dispose来实现相同的结果; 实际上,这就是编译器如何翻译using语句的方式。

3

使用 using 块时,如果括号内的对象实现了 IDisposable 接口,则该对象将被处理。

即使 foo() 失败,它仍将被处理。

using 语句中的对象必须实现 IDisposable 接口。

此外,这些问题 "C# 中 using 的用法""using 语句 vs try finally" 进一步阐述了 using 语句的用途和实用性。

第 8.13 节的 C# 语言规范 明确详细地说明了 using 语句。


2
您的using代码等效于:
IDatabaseConnectivityObject databaseConnectivityObject = new IDatabaseConnectivityObject ();
try
{
//To do code here
}
finally
{
    if(databaseConnectivityObject!=null)
    {
       databaseConnectivityObject.Dispose();
    }
}

一个using语句主要分为三个部分:

  1. 获取
  2. 使用
  3. 释放

首先,在try块中获得资源并使用finally语句进行处理。最后,在finally块中释放对象,如上面的等效代码所示...


1
我认为值得指出的是,通常情况下,当解释空值测试时,它会被优化掉。有人可能会想自己使用try-finally进行微观优化。这本来就是个坏主意(可读性的降低不值得),而且它甚至无法提供他们认为可能存在的微小好处,这将进一步打消他们的念头。 - Jon Hanna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接