是这个吗
try
DoSomethingThatMightThrowAnException;
except
on E : ESyntaxError do
begin
if (E.ErrorCode = errMissingBracket) then
HandleError
else
raise;
end;
end;比这还慢?
try
DoSomethingThatMightThrowAnException;
except
on E : EMissingBracketSyntaxError do
begin
HandleError;
end;
end;预计会有什么不同?有关系吗?请注意,通过调用堆栈,这可能会发生多次。
发布于 2011-06-22 20:07:09
我已经快速地看了一下编译器为上面的代码片段提供的汇编程序。事实证明,紧跟在jmp @HandleOnExeption后面的字节包含数据,比如在on子句中使用的异常类指针(如果有的话)。
我不是很精通汇编语言,不知道到底发生了什么,但足以理解大致发生了什么,并得出这样的结论:
我怀疑System.pas的HandleOnException已经执行了call @IsClass,如果找不到合适的处理程序,就会传递异常,所以如果您使用on e:Exception并重新引发,这将添加一些代码并额外调用两次:
call @RaiseAgain (在异常重新引发的情况下)所以,这是有区别的。一个小问题,但它还是存在的。
发布于 2011-06-22 20:04:57
预计会有什么不同?
您所描述的场景之间的差异很小。
然而,是错误的,这是引发异常和根本不引发异常(使用错误结果)之间的显着区别。
这有关系吗?请注意,通过调用堆栈,这可能会发生多次。
你应该只在“异常情况”中使用异常。如果错误频繁,特别是在循环中,那么它应该被提升到一个完全成熟的用例场景。
如果你不这样做,开始时看似简单的事情很快就会恶化成除了块以外的变得比例程的其余部分更大的情况。
通常,检查条件并将其作为主线代码中的显式分支来处理应该是相当简单的。
即,不是:
begin
try
//Do1
//Do2 (possibly raising an exception that you can handle)
//Do3
//Do4
except
//Dealing with main-line cases in exception handlers is
//very bad, leading to difficult to read code in the future.
end;
end;而是这样写:
begin
//Do1
//LDo2Result := Do2
//NOTE: Do2 can still raise exceptions in EXCEPTIONAL situations.
// But for "main-line" use-case scenarios should rather return explicit
// results that can be handled.
if LDo2Result = d2rNoErrors then
begin
//Do3
//Do4
end;
if LDo2Result = d2rBracketMissing then
begin
//DoX
end;
end;在性能和可维护性方面,上述两种方案通常都比您所描述的任何一种方案都要好。然而,就像所有与软件开发相关的事情一样:你会得到一个指南和技术的调色板,但你需要应用你的经验来选择“目前手头的特定工作的最佳工具”。
发布于 2011-06-22 19:16:03
在实际应用程序的上下文中,性能差异可以忽略不计。在我的机器上,引发和处理异常(使用null处理程序)大约需要0.3毫秒,如果我添加大量日志记录,大约需要1.3毫秒。因此,如果异常确实是异常的,它不会对您的应用程序的性能造成丝毫的影响。
https://stackoverflow.com/questions/6438482
复制相似问题