Using finally instead of catch
我已经见过这种模式几次了:
1 2 3 4 5 6 7 8 9 10 11 | bool success = false; try { DoSomething(); success = true; } finally { if (!success) Rollback(); } |
我一直在想:为什么这比使用catch进行回滚更好?
1 2 3 4 5 6 7 8 9 | try { DoSomething(); } catch { Rollback(); throw; } |
确保在失败时回滚更改的两种方法之间有什么区别?
我在这里发布了一些代码,即使它与问题并不相关(稍后将删除)。
使用此程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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"); } } } |
堆栈跟踪(查看行号!)保留,但在
如果您不关心这个特定的代码,那么应该使用哪种类型的异常:
1 2 3 4 5 6 7 8 9 | try { DoSomething(); ok = true; } finally { if(!ok)Rollback(); } |
这将使调用堆栈保持其原始形式的100%。同样,如果您使用这样的异常处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | try { DoSomething(); ok = true; } catch(FirstExcetionType e1) { //do something } catch(SecondExcetionType e2) { //do something } catch(Exception e3) { //do something } finally { if(!ok)Rollback(); } |
在末尾使用finally可以使代码比从每个catch语句调用rollback更具可读性。
我不确定这是否只是轶事证据,但我个人使用这种模式的原因非常实际:当
但是,您不希望在那里执行任何可以引发异常的操作。
当然,在这种特定的情况下,只有在出现错误时才需要回滚,但是作为一种通用模式,
这里明确的目标是在出现任何错误时调用
您提到该项目是从Java移植的。在爪哇中,可以使用eDCOX1(13)来重新抛出类似于C语言中的异常。您还可以抛出一个仍将维护调用堆栈的新异常(等)。第二个是C语言中的更简单/更简单(虽然不是很多),第一个有实际的Java工作的优势。