当前位置:  开发笔记 > 编程语言 > 正文

这些尝试/捕获量是否相同?

如何解决《这些尝试/捕获量是否相同?》经验,为你挑选了2个好方法。

脚本

我有一个进行数据库操作的方法(比方说).如果在该操作期间引发任何异常,我只想将该异常抛给调用者.我不想在catch块中执行任何特定任务,假设调用者将对该异常执行任何操作.在这种情况下,哪一种是适当的异常处理技术?

try
{
    // Some work that may generate exception
}
catch(Exception)
{
    throw;
}
finally
{
    // Some final work
}

以上是等于以下try/catch/finally吗?

try
{
    // Some work that may generate exception
}
catch
{
    throw;
}
finally
{
    // Some final work
}

以上是等于下面的try/finally吗?

try
{
    // Some work that may generate exception
}
finally
{
    // Some final work
}

哪一个比另一个好?应该使用哪一个?



1> Venemo..:

不,他们不等同.在某些情况下,它们可能相同,但一般的答案是否定的.

不同种类的catch

catch 具有指定异常类型的块

以下内容仅捕获从中继承System.Exception然后执行finally块的托管异常,无论是否抛出异常,都会发生这种异常.

try
{
   // Some work that may generate exception
}
catch (Exception)
{
   throw;
}
finally
{
   // Some final work
}

catch 没有指定异常类型的块

catch没有类型说明符的以下块也将捕获不一定由托管System.Exception对象表示的非托管异常,然后执行该finally块,无论是否抛出异常,都会发生该块.

try
{
   // Some work that may generate exception
}
catch
{
   throw;
}
finally
{
   // Some final work
}

finally块没有catch

如果您根本没有catch阻止,finally无论是否发生异常,您仍将执行.

try
{
   // Some work that may generate exception
}
finally
{
  // Some final work
}

他们什么时候相同?

如果您的catch块没有指定异常并且只包含该throw;语句,则后两个确实是等效的.如果您不关心非托管异常,并且您的catch块仅包含该throw;语句,则可以认为这三者都是等效的.

笔记

关于 throw

以下两段代码包含一些细微差别.后者将重新抛出异常,这意味着它将重写异常的堆栈跟踪,因此这些绝对等同:

catch (Exception e)
{
    throw;
}

catch (Exception e)
{
    throw e;
}

如果您使用finallya IDisposable,以下两段代码几乎相同,但有一些细微差别:

当对象为null时,using语句不会给你一个NullReferenceException

当使用try- finally技术时,变量仍然在范围内,尽管在处理之后使用任何对象都是非常不鼓励的.但是,您仍然可以将变量重新分配给其他内容.

东西obj = null; try {obj = new Something()// do something} finally {obj.Dispose(); }

using (var obj = new Something())
{
    // Do something
}


@Bhuban你没有理由想要这样做.您要么重新抛出,要么想要抛出另一个异常(可能将原始异常作为`InnerException`).当然,所有需要完成的工作都会对性能产生影响 - 只有您可以判断应用程序中的性能影响是否明显,并且只能通过测量.一般来说,异常是*例外*,因此在特殊情况下代价很高的代码通常很好 - 如果你发现抛出异常会使你的程序太慢,你应该修复底层问题.

2> Eric Lippert..:

到目前为止,你有一些很好的答案,但到目前为止他们没有提到一个有趣的区别.考虑:

try { ImpersonateAdmin(); DoWork(); } 
finally { RevertImpersonation(); }

VS

try { ImpersonateAdmin(); DoWork(); }
catch { RevertImpersonation(); throw; }
finally { RevertImpersonation(); }

假设DoWork抛出.

现在第一个问题是"是否存在可以处理此异常的catch块",因为如果答案为"否",则程序的行为是实现定义的.运行时可能会选择立即终止进程,它可能会选择在终止进程之前运行finally块,它可能会选择在未处理的异常点启动调试器,它可能会选择执行任何喜欢的操作.具有未处理异常的程序可以执行任何操作.

所以运行时开始寻找一个catch块.这个try语句中没有,所以它查找调用堆栈.假设它找到一个带有异常过滤器的.它需要知道过滤器是否允许处理异常,因此过滤器在模拟被还原之前运行.如果过滤器意外或故意做了只有管理员可以做的事情,它就会成功!这可能不是你想要的.

在第二个示例中,catch立即捕获异常,恢复模拟,抛出,现在运行时开始寻找catch块来处理重新抛出.现在,如果有一个过滤器,它将模拟恢复运行.(当然最终会再次恢复;我认为恢复模仿在这里是幂等的.)

这是这两个代码片段之间的重要区别.如果绝对禁止积极任何代码,一看就知道是由尝试搞砸了,并通过清理全局状态最终,那么你最后才赶上."最后"并不意味着"立即",它意味着"最终".

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有