【问题标题】:Can .NET SqlConnection.Dispose() throw an exception?.NET SqlConnection.Dispose() 可以抛出异常吗?
【发布时间】:2015-02-13 20:15:22
【问题描述】:

SqlConnnection 对象的Dispose 方法是否有可能抛出异常?它总是显示在 try-catch 之外的 finally 块中。如果 using 块等价于 try...finally,然后调用 Dispose,那么 Dispose 抛出的异常似乎也会有问题。

【问题讨论】:

  • 我认为任何方法都可以抛出异常。您可以在 finally 中放置并尝试 catch。
  • SqlConnection(几乎)如果您尝试连续两次(第二次)调用Dispose(),肯定会抛出异常。
  • @EkoostikMartin 会吗?我相信 Dispose 所做的只是关闭非托管连接 - 为什么尝试再次关闭它会导致异常?

标签: sql .net exception dispose unmanaged


【解决方案1】:

技术上它可以,但它不应该

CA1065: Do not raise exceptions in unexpected locations

IDisposable.Dispose 方法不应引发异常。 Dispose 通常被称为 finally 子句中清理逻辑的一部分。因此,从Dispose 显式抛出异常会强制用户在 finally 子句中添加异常处理。 Dispose(false) 代码路径不应该抛出异常,因为它几乎总是从终结器调用。

Dispose Dos and Don'ts:

不要在 Dispose 中抛出异常。调用 Dispose 的对象应该不会出错。

这个故事的寓意似乎是从Dispose 抛出的异常是一件非常糟糕的事情(出于您提到的某些原因),应该尽可能高地处理(您对此无能为力,并且可能无法从中恢复)。

【讨论】:

  • 我猜所有的 .NET 库都坚如磐石,不会抛出异常,而且只有在用户定义或第三方代码引入问题时才会发生这种情况?
  • 这可能过于笼统了 - 我确信在某些情况下 .NET 库可能会引发异常,但您将如何处理呢?除非您可以做一些不同的事情来处理它,否则捕获异常没有多大意义。你可能不能就好像什么都没出错一样继续下去(至少在那个级别上没有)。
【解决方案2】:

一般来说,如果系统的状态与周围代码所期望的一致,则代码块应该正常完成,如果不匹配,则抛出异常。然而,.NET 中的 try/catch/finally 构造有一个弱点,它流入了设计用于使用它的 IDisposable 接口(通过像 using 这样的语言构造):一种方法

void Test()
{
    try
    {
      doSomething();
    }
    finally
    {
      doCleanup();
    }
}

应该只在doSomething()doCleanup() 都成功的情况下正常退出,但是如果doSomething() 抛出异常,则Test() 方法作为一个整体应该抛出该异常或使其发生可以记录下来。满足这两个要求将要求doCleanup() 在成功调用doSomething() 之后运行它的异常,但不遵循引发异常的调用,或者它抛出的任何异常都包含有关从@ 抛出的异常的信息987654330@.

不幸的是,没有方便的方法来编写 finally 块来根据 try 的结果改变其行为,也没有任何方法可以让从 finally 调用的 Dispose() 方法来做所以。因此,Dispose 实现有必要尝试猜测在操作失败时正常退出是否更邪恶,或者抛出可能覆盖早期保存有用信息的异常。后者有些邪恶,但通常不如前者邪恶。

以伪代码为例:

RenameFile(mainFileName, backupFileName);
using(outFile = File.Create(mainFileName);
{
  writeDataToNewFile(outFile);
}
DeleteFile(backupFileName);

如果在关闭输出文件时出现问题并且异常被传播到using 块之外,则备份文件将保持原样,以后可能会恢复。如果 using 块被允许正常完成,尽管失败导致主文件无法正确写入,备份文件将被删除,可能会破坏其中包含的一些数据的唯一副本。

Dispose 不应该抛出异常的想法与以下事实有关:通常没有好的方法来处理从 Dispose 抛出的异常。然而,更大的问题是,在不知道调用它的环境的情况下,没有很好的方法来处理在Dispose 期间出现的问题。从Dispose 抛出异常可能有点邪恶,但在存在真正问题的情况下,仍然比让它正常完成更邪恶。

【讨论】:

    猜你喜欢
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多