一般可以知道在for循环中放置一个case是否会导致错误的汇编。我主要对Delphi感兴趣,但这在风格和性能方面都是一个有趣的编程问题。
这是我的密码!
case ResultList.CompareType of TextCompareType: begin LastGoodIndex := -1; for I := 1 to ResultList.Count -1 do if (LastGoodIndex = -1) and (not ResultList[I].Indeterminate) then LastGoodIndex := I else if not ResultList[I].Indeterminate then begin if (StrComp(ResultList[LastGoodIndex].ResultAsText, ResultList[I].ResultAsText) > 0) and (Result FalseEval) then Result := TrueEval else Result := FalseEval; LastGoodIndex := I; end; end; end; NumericCompareType: begin //Same as above with a numeric comparison end; DateCompareType: begin //Same as above with a date comparison end; BooleanCompareType: begin //Same as above with a boolean comparison end;
或者我可以写
begin LastGoodIndex := -1; for I := 1 to ResultList.Count -1 do if (LastGoodIndex = -1) and (not ResultList[I].Indeterminate) then LastGoodIndex := I else if not ResultList[I].Indeterminate then begin case ResultList.CompareType of TextCompareType: begin if (StrComp(ResultList[LastGoodIndex].ResultAsText, ResultList[I].ResultAsText) > 0) and (Result FalseEval) then Result := TrueEval else Result := FalseEval; LastGoodIndex := I; end; NumericCompareType: begin //Same as above with a numeric comparison end; DateCompareType: begin //Same as above with a date comparison end; BooleanCompareType: begin //Same as above with a boolean comparison end; end; end; end;
我不喜欢第二种方式,因为我问一个问题,我知道在for循环中的答案,我不喜欢第一种方式,因为我正在重复我用来弄清楚哪个代码我的对象包含有效信息。
也许有人可以建议的设计模式可以一起避开这一点。
答案 0 :(得分:4)
通常,无法知道将为特定编程语言结构生成哪些汇编语言输出。每个编译器都不同。即使对于特定的编译器,每个应用程序也会不同,编译器将有不同的优化策略。
如果您真的担心它,最简单的方法是编译程序并查看它生成的内容。使用代码和优化设置,直到它看起来如何。 (或者手工编写汇编。)
常见的建议是尽可能编写最清晰的代码,除非确实需要,否则不要担心调整性能。
答案 1 :(得分:2)
为什么不使用子类?
这样可以节省案例陈述的使用。
TComparer = class
protected
function Compare(const AItem1, AItem2: TItem): Boolean; virtual; abstract;
public
procedure DoCompare(ResultList: ...);
end;
TTextComparer = class (TComparer)
protected
function Compare(const AItem1, AItem2: TItem): Boolean; override;
end;
procedure TComparer.DoCompare(ResultList: ...);
var
LastGoodIndex, I : Integer;
begin
LastGoodIndex := -1;
for I := 1 to ResultList.Count -1 do
if (LastGoodIndex = -1) and (not ResultList[I].Indeterminate) then
LastGoodIndex := I
else if not ResultList[I].Indeterminate then begin
if Compare(ResultList[LastGoodIndex], ResultList[I]) then
Result := TrueEval
else
Result := FalseEval;
end;
end;
function TTextComparer.Compare(const AItem1, AItem2: TItem): Boolean;
begin
Result := StrComp(ResultList[LastGoodIndex].ResultAsText,
ResultList[I].ResultAsText) > 0)
end;
答案 2 :(得分:1)
我怀疑使用lambda或闭包甚至只是函数引用更有效。我的Pascal生锈了,所以我的例子是perl:
my %type = (
TextCompareType => sub { $_[0] lt $_[1] },
NumericCompareType => sub { $_[0] < $_[1] },
DateCompareType => sub { ... },
BooleanCompareType => sub { ... },
);
for (my $i = 1; $i <= $#list; ++$i)
{
if ( $type{$ResultList{CompareType}}->($list[$i-1], $list[$i]) )
{
$result = 1; # ?
}
}
我并没有真正关注你的大部分代码,但我认为我已经捕获了问题的本质而没有完全捕获代码。
另一个解决方案是将比较器对象创建为基类比较器类的子类,然后调用对象的比较函数,但是你确实提到了保持结构而不是OO。