我已经看到了这种模式现在几次:
bool success = false;
try
{
DoSomething();
success = true;
}
finally
{
if (!success)
Rollback();
}
我一直在想:为什么这比使用渔获回滚更好?
try
{
DoSomething();
}
catch
{
Rollback();
throw;
}
什么是确保更改将回滚失败的两种方法之间的差异?
这里的明确目标是使Rollback
到任何错误的情况下被调用。 这两个代码段实现这一目标。 第一次使用了最后,这始终运行,用来验证的最后一行try
块顺利到达。 所述第二捕获任何错误,回滚事务,然后重新抛出这是捕捉到的异常。 无论是代码片段的结果是,抛出的异常会导致回滚,同时仍然向上冒泡到一个新的水平。
你提到的项目是从Java移植。 在Java中,你可以 重新抛出异常类似于您如何在C#中使用throw;
。 您也可以抛出一个新的异常 ,将仍然保持调用堆栈(等人)。 第二个是有点清晰/ C#中简单的(不是很多,虽然)和第一有在Java中实际工作书面的优势。
我在这里发布,即使它没有真正涉及到的问题(稍后会删除)一些代码。
有了这个程序:
using System;
namespace testcs
{
class Program
{
static void Main(string[] args)
{
try
{
try
{
foo();
foo();
foo();
}
catch
{
throw;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void foo()
{
throw new Exception("oops");
}
}
}
堆栈跟踪(看行号!)是保留的,但里面main
功能,你会看到“第19行”,其中线throw
是不是真行,其中foo()
被调用(13号线)。
在finally
陈述通常用于清理资源。 该Rollback()
如果异常是不可回滚事务的唯一原因,方法可能是正确的使用存在。 Close()
或Dispose()
的方法是总理候选人在finally块结束。
但是,你不想在那里执行任何可以抛出异常。
如果没有什么类型的异常,你正赶上使用这个特殊的代码护理:
try
{
DoSomething();
ok = true;
}
finally
{
if(!ok)Rollback();
}
这将在其原来的形式为100%保留调用堆栈。 此外,如果你使用异常MACHING这样的:
try
{
DoSomething();
ok = true;
}
catch(FirstExcetionType e1)
{
//do something
}
catch(SecondExcetionType e2)
{
//do something
}
catch(Exception e3)
{
//do something
}
finally
{
if(!ok)Rollback();
}
使用最后在年底可以使你的代码不是从每一个catch语句调用回滚更具可读性。
我不知道这是不是只是传闻 ,但我个人已经使用这种模式的一个很实际的理由:当DoSomething
抛出一个异常,Visual Studio调试器将打破DoSomething
在异常的第一个版本出现,而这将打破在throw;
在第二个版本。 这允许检查应用程序状态之前Rollback
一切都已经清理干净。
finally
总是执行,不仅捕捉异常。
当然,在这种特殊情况下,当出现错误回滚时,才需要,但作为一个普通模式, try-finally
可能是资源管理更加有用(其中往往你需要确保你总是Close()
或Dispose()
你的资源的正确)。 特别是如果代码的作者是从Java背景的,其中这个成语是更为普遍。