for循环中的case(或switch)或case(或switch)中的for循环?

时间:2008-10-28 20:13:51

标签: language-agnostic coding-style performance

一般可以知道在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循环中的答案,我不喜欢第一种方式,因为我正在重复我用来弄清楚哪个代码我的对象包含有效信息。

也许有人可以建议的设计模式可以一起避开这一点。

3 个答案:

答案 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。