再论Case和If语句的优劣(50分)

  • 主题发起人 主题发起人 DarwinZhang
  • 开始时间 开始时间
D

DarwinZhang

Unregistered / Unconfirmed
GUEST, unregistred user!
在如下帖子中
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1358621
讨论的一下Case和If语句的优劣,
我认为,其实使用Case语句必须要具备一下情况才能考虑使用:
1各种情况的值有若干段是连续
2各种情况发生概率基本相差不大

比如
i有等于 0,1,2,3,4, 11,12,13,14,15,16 就比较适合用Case语句
假如是有 1, 333, 52432, 123403, 2234233, 134836263 就不适合用Case语句,还是用
if then else比较好。
另外,
case i of
0: ...
1: ...
2: ...
3: ...
11:...
12:...
13:...
14:...
............
end

并且i等于各种值的概率相差不是很悬殊的情况下才比能使用。
假如 i=13的情况就占据了 99.9%的情况,那么还是用一句 if i=13 then... else...
比较恰当。

以上是本人的鄙解,希望大家提出不同看法。
 
我认为,效率已经不是大问题,只要有多项,且能用Case的就用Case
比如在一个过程中处理一个消息,可以用IF,但如果下次要增加一个功能,
你可以再加一个IF,再下次呢.....所以我一般用CASE,修改方便些.
 
[:D]同意楼上,CASE逻辑要清楚些,维护成本低。前一段写了一个过程800多句,
先用IF后改CASE。头都大了。
 
能用Case的用Case,提高效率,不能用Case的,用If也无妨,情况不同,用的不同;
 
>假如是有 1, 333, 52432, 123403, 2234233, 134836263 就不适合用Case语句,还是用
>if then else比较好。

也可以用的啊:
case xxx of
1, 333, 52432, 123403, 2234233, 134836263:
;
else
;
end;
if不好阅读。
 
嗬嗬,各抒己见,其实无所谓。
 
虽然当前的程序,效率已经不是最重要的,但也不能完全走到另外一个极端,根本不考虑效率.
另外,有人认为If then else 的可读性不好,这完全是一种误会,因为如下的写法可读性
一点也不会比Case差:
{开始判断}if i=1 then begin // i=1时
...
end else if i=2 then begin // i=1时
...
end else if i=3 then begin // i=1时
...
...
end
// 判断完毕
而且增加一种情况只要Copy-Paste就可以轻松搞定.一点也不会比Case麻烦.
所以,我才讨论Case 和 If then else的效率问题.
因为Case是依靠指针跳转来实现情况跳转的,但它的初试化语句有时比较多,
而且当变量相差很大时就会发生效率非常低下的情况.
另外 to Milpas: 你的
case xxx of
1, 333, 52432, 123403, 2234233, 134836263:
;
else
;
end;
显然不对,应该是:
Case i of
1: begin
....
end;
333: begin
...
end;
52432: begin
...
end;
123403: begin
...
end;
2234233: begin
...
end;
134836263: begin
...
end;
end;
而If then else 可以写成
{开始判断}if i=1 then begin
...
end else if i=333 then begin
...
end else if i=52432 then begin
...
end else if i=123403 then begin
...
end else if i=2234233 then begin
...
end else if i=134836263 then begin
...
end
// 判断完毕
这时侯,Case的效率就比If低了.

另外to ysai: 消息处理我认为是应该用Case语句,因为消息值大多分段连续变化,
而且概率基本一致,所以不要使用If then else.
 
to DarwinZhang
Milpas的没错,执行效率先别管,毕竟它们两个差不多,这样写起码快些,可读性也不差
 
同DarwinZhang,
 
// 而且当变量相差很大时就会发生效率非常低下的情况.
这是没有根据的说法。这种情况 Delphi 会另行处理,但是仍然是跳转表!
怎么能认为效率低呢?

当然,我从来也[red]没有[/red]说过非 case 不用。我自己也经常用 if then else,
这很正常。视不同情况而定
以下是我同一个单元里面的两段代码,分别用了 case 和 if then else,
大家看一下:

一:
if Trunc(ArrvDatetime) = Trunc(LeavDatetime) then // the first &amp
last day
begin
Br.Checked := (ArrvHour < 8) and (LeavHour > 8);
Di.Checked := (ArrvHour < 13) and (LeavHour > 13);
Su.Checked := (ArrvHour < 18) and (LeavHour > 18);
end else
if Trunc(Today) = Trunc(ArrvDatetime) then // the first day
begin
Br.Checked := ArrvHour < 8;
Di.Checked := ArrvHour < 13;
Su.Checked := ArrvHour < 18;
end else
if Trunc(Today) = Trunc(LeavDatetime) then // the last day
begin
Br.Checked := LeavHour >= 8;
Di.Checked := LeavHour >= 13;
Su.Checked := LeavHour >= 18;
end else // in the middle
begin
Br.Checked := True;
Di.Checked := True;
Su.Checked := True;
end;

二:
case Key of
XK_NEXTEDIT: ActivateNextCtrl(EditCtrlType(Sender));
XK_LASTEDIT: ActivateLastCtrl(EditCtrlType(Sender));
XK_NEXTGROUP: ActivateNextGroup(EditCtrlType(Sender));
XK_LASTGROUP: ActivateLastGroup(EditCtrlType(Sender));
end;

说出我的经验原则:要是判断条件相同,则用 case,否则用 if then else。
当然,这也[red]不绝对[/red],仍有浮动的余地。

 
有必要看这个效率问题,偶页来听课,不过感觉好像没必要,楼主要写什么程序,
这个也在考虑之列?
 
to beta:
你的:
//而且当变量相差很大时就会发生效率非常低下的情况.
这是没有根据的说法。这种情况 Delphi 会另行处理,但是仍然是跳转表!
怎么能认为效率低呢?
当然是错误的!
你看一下汇编代码就知道了!
假如是连续情况的Case比如:
Case i of
0: ...
1: ...
2: ...
3: ...
4: ...
5: ...
end;
它的汇编代码大约是这样的:
cmp eax,$0a
jnbe +$00000153
jmp dword ptr [eax*4+$0044f116]
....
这就是根据函数地址指针表跳转。
假如是这样的:
Case i of
1: ...
123: ...
1234: ...
12345: ...
end;
那么汇编代码大约是:
dec eax
jz +$15
sub eax,$7a
jz +$1e
sub eax,$00000457
jz +$25
sub eax,$00002b67
jz +$2c
....
其实效率和If then else 差不多。
假如i=1234的概率是90%,那么用If then else 优化的可读性比Case语句好得多。

 
我之所以要写这篇贴子,主要是想更深入的讨论一下Case和If语句,
发现一下自己观点的不足或者是错误的地方。

另外,Case语句对 “或” 逻辑(or)的支持非产好,比 If then else 简洁得多。
当然,Case语句对and,not,xor这些逻辑的支持就不好。
比如
Case i of
3,5,7,11,13,17,19: ...
1,9,15: ...
2,4,6.8,10,12,14,16,18: ...
end;
要用If then else实现起来可读性就很不好.
虽然效率可能会 if then else 好,但是我仍然赞成用 case 来写.
 
//当然是错误的!
//你看一下汇编代码就知道了!
//假如是这样的:
//Case i of
// 1: ...
// 123: ...
// 1234: ...
// 12345: ...
//end;
//那么汇编代码大约是:
// dec eax
// jz +$15
// sub eax,$7a
// jz +$1e
// sub eax,$00000457
// jz +$25
// sub eax,$00002b67
// jz +$2c
// ....

你没有仔细看我的那篇心得吧,我已经讲的很清楚了,你看到的汇编代码之所以会这样,
没有用跳转表,是因为你的选项太少!
当然,在选项少的时候,case 的效率略低于 if then,但是在选项少的时候也就没有太大
必要考虑效率问题吧。

其他的东西如我前面的回复所说。

 
我是个刚踏近大富翁的delphi新手,我想发表一点我的看法:
Case i of 中i只能是个常量,而不能是个变量,所有在待判断的值是变量时用Case似乎无法实现!

初来乍到,请多多关照!!
 
本身if then的效率比case的效率高,但是在条件非常多的情况下,case 1.。。。。。。。n则反之
 
我的意思是说,在case i of x 中,x只能的个常量,而不能是个变量!我的上一个贴子中写错了!
 
后退
顶部