使用 try/finally try/ except 而不是 begin/end 被认为是不好的做法或存在任何缺点吗?
在我维护的一些应用程序的许多地方,我发现代码在 for 循环
中使用 try/finally
或 try/ except
块> 或 if
语句避免使用 begin/end
考虑下一个代码(不是生产代码,只是一个示例)
{$APPTYPE CONSOLE}
{$R *.res}
uses
Classes,
SysUtils;
Procedure TestNoBeginEnd;
var
i : Integer;
L1 : TStringList;
begin
for i := 1 to 10 do
try
L1:=TStringList.Create;
try
L1.Add('Bar');
L1.Add(IntToStr(i));
L1.Add('Foo');
finally
Writeln(L1.Text);
L1.Free;
end;
except
on E: Exception do
Writeln('Opps '+E.ClassName, ': ', E.Message);
end;
end;
begin
try
TestNoBeginEnd;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
问题,被认为是一种不好的做法,代码味道或存在使用 try/ 的任何缺点最后还是尝试/除了而不是delphi中的开始/结束?
更新
我对愚蠢的示例代码感到抱歉,只是为了澄清 try/finally 和 try/ except 并不假装替换 begin/end ,只是为了避免使用它( begin/end ) 当存在使用 try/finally 或 try/ except 不需要开始/结束的情况时。
In many places in some Apps which I maintain , I've found code which uses a try/finally
or try/except
block in a for loop
or if
sentence avoiding the use of begin/end
Consider the next code (not production code, just a sample)
{$APPTYPE CONSOLE}
{$R *.res}
uses
Classes,
SysUtils;
Procedure TestNoBeginEnd;
var
i : Integer;
L1 : TStringList;
begin
for i := 1 to 10 do
try
L1:=TStringList.Create;
try
L1.Add('Bar');
L1.Add(IntToStr(i));
L1.Add('Foo');
finally
Writeln(L1.Text);
L1.Free;
end;
except
on E: Exception do
Writeln('Opps '+E.ClassName, ': ', E.Message);
end;
end;
begin
try
TestNoBeginEnd;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
The Question, Is considered a bad practice, code smell or exist any drawback using a try/finally or try/except instead of begin/end in delphi?
UPDATE
I'm sorry by the silly sample code, just for clarify the try/finally and try/except doesn't pretend replace the begin/end , just to avoid to use it (the begin/end) when exist a case when the use of the try/finally or the try/except doesn't requires a begin/ end.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当 try finally/ except 为您将相同的代码包装在块中时,省略 begin end 并没有什么问题。请记住,try 块比 begin 块有更多的开销。这种开销通常可以忽略不计,但我发现它在循环中产生有意义的差异,特别是在重复引用的方法中的循环。
考虑到上述细节,您的示例有些糟糕,因为它在循环中重复增加了不必要的开销。每当您可以将 try 块移出循环时,这都是一件好事。在您的示例中,如果您必须能够捕获每次循环迭代的异常,那么下面的代码会更有效,如果没有,也将 except 块移出。
There is nothing wrong with omitting the begin end when a try finally/except wraps the same code in a block for you. Just remember that try-blocks have more overhead than a begin-block. This overhead is usually negligible, but I have found it to make meaningful differences when in loops, specially loops in methods that are referenced repeatedly.
Taking the above details in mind, your example is somewhat poor due to the fact that it adds unneeded overhead repeatedly in the loop. Whenever you can move try blocks out of a loop, it's a good thing. In your example if you MUST have the ability to catch an exception for each loop iteration, the below code would be more efficient, if not, move the except block out also.
我个人认为没有必要在
try..finally/ except..end
周围添加额外的begin..end
,特别是当代码的机会很少时在try
之前添加,或者在end
之后添加。话虽这么说,问题更多的是我们是否需要在
..do
或..then
之后系统地添加begin..end
当只有一条指令时(在您的情况下是try..
指令)。这主要是风格和习惯的问题,有些人更喜欢防御性地编写代码并系统地设置开始..结束,其他人则尝试尽可能避免不必要的行。
当涉及相当多的行时,我倾向于添加
begin..end
以使范围更加明显。我想说,请运用良好的判断力,看看稍后修改代码的人(或您)可能会错过预期的范围。
I personally don't see the need to add the extra
begin..end
around atry..finally/except..end
, especially when there is little chance of code being added just before thetry
or certainly after theend
.That being said, the question would be more whether we need systematically a
begin..end
after a..do
or a..then
even when there is only a single instruction (in your case atry..
instruction).It's mostly a question of style and habit, some people prefer to code defensively and systematically put a begin..end, others try to avoid unnecessary lines as much as possible.
When a fair number of lines are involved, I tend to add the
begin..end
to make the scoping more obvious.I'd say, use good judgment and see what the chances are that someone (or you) modifying the code later could miss the intended scope.
首先要事。 Begin/End 与 Try/Etc 不同。后者第一个表示一组指令,而第二个表示单个指令(可能包含很多指令)。
编辑:
如果我理解这个问题(既然你已经编辑了它),你会问是否可以在没有开始/结束的情况下使用一次尝试/等等。是的,你可以这样做,因为 try/etc 是单个语句。事实上,我什至想说,避免太多无用代码可能是一件好事。
编辑之前:
那这是什么意思?这意味着如果该函数中发生错误,它会被记录下来,但基本上会被忽略。
除非有非常好的异常处理并且代码升级异常或正确恢复我会说这是不好的做法。
在您的示例中,所有异常处理程序所做的就是说“Opps”(哎呀?)。那有什么好处呢?当然,这可能只是一个示例,因此我会检查代码以了解它的真正作用。我相信写这篇文章的人通常试图处理错误,但实际上使用这种模式使代码的可靠性变得更差。
我使用“异常处理程序用于异常情况”的一般情况,我可以在其中恢复或需要让某人/事物知道。大多数情况下,我发现没有人能够处理该错误,并且系统必须按照设计进行降级。这是异常处理程序将安全记录并传递异常的地方。
后一种情况我扩展到所有“系统中的大边界”。即我将在服务/API 边界收集异常并适当地记录/包装。
(请注意,有时不良 API 在非特殊情况下使用异常,在这种情况下,您可以安全地添加异常处理程序来包装不良设计)。
First things first. Begin/End is not the same as Try/Etc. The latter first denotes a set of instructions, while the second is a single instruction (which contains possibly lots of instructions).
Edit:
If I undertand the question (now that you've edit it) you're asking if one try/etc can be used with out a begin/end. Yes you can do this, because try/etc is a single statement. In fact I'd go as far as to say it's probably a good thing to avoid too much no use code.
Before edit:
So what does that mean? Well it means that if an error occurs in that function it's gets logged, but essentially ignored.
Unless there is really good exception handling and the code escalates exceptions or recovers correctly I'd say this was bad practise.
In your sample all the exception handler does is say Opps (oops?). What good is that? Sure it's probably only a sample and as such I'd examine the code to see what it really does. I beleive that the person who wrote this was trying to handle errors generally, but is actually making the reliability of the code far far worse using this pattern.
I use the general case of 'Exception Handlers are for Exceptional Cirmcumstances' where I can recover or I need to let someone/thing know. Mostly I find that no one can handle the error and the system has to degrade as per design. This is where the exception handlers will log safely and pass teh exceptions on.
The latter case I extend to all 'big boundaries in the system'. i.e. I'll collect exceptions at Service/API boundaries and log/wrap appropriately.
(note sometimes bad APIs use Exceptions for non exceptional circumstances, in this case you can safely add an exception handler to wrap the bad design).
您对问题的编辑从根本上改变了问题。你至少应该改变标题,现在我想知道这个问题是否可以挽救(-1)。
也就是说,在解决您最初的问题时:
当 Begin/End 语句就足够时,永远不应使用 Try/Finally 或 Try/Except 语句。除了 Try 语句向编译后的代码添加(微小甚至不易察觉的)额外指令这一事实之外,它们还暗示了不存在的代码必要性:
只是不这样做。
Your edit on the question radically changed the question. You should have changed the title at least, and right now I wonder if the question is salvageable at all (-1).
That said, when addressing your original question:
A Try/Finally or Try/Except statement should never be used when a Begin/End statement would suffice. Besides the fact that Try-statements add (tiny or even unnoticeable) extra instructions to the compiled code, they imply code necessities which aren't there:
Just not do it.