Случай (или переключатель) в цикле for или для цикла в случае (или switch)? - PullRequest
0 голосов
/ 28 октября 2008

Можно ли вообще знать, приведет ли размещение кейса в цикле for к неправильной сборке. Меня интересует в основном 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 ]

4 голосов
/ 28 октября 2008

В общем, нет способа узнать, какой вывод на ассемблере будет сгенерирован для конкретных конструкций языка программирования. Каждый компилятор отличается. Даже для конкретного компилятора каждое приложение будет отличаться, и у компилятора будут разные стратегии оптимизации.

Если вы действительно беспокоитесь об этом, проще всего скомпилировать программу и посмотреть, что она генерирует. Поиграйте с кодом и настройками оптимизации, пока все не будет выглядеть так, как вы хотите. (Или напишите сборку от руки.)

Обычный совет - просто написать максимально понятный код и не беспокоиться о настройке производительности, если только вам это не нужно.

2 голосов
/ 28 октября 2008

Почему бы не использовать подклассы?

Это экономит использование оператора case.

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;
1 голос
/ 28 октября 2008

Я подозреваю, что более эффективно использовать лямбду или замыкание или даже просто ссылку на функцию. Мой Паскаль заржавел, поэтому мой пример - 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; # ?
    }
}

Я не совсем слежу за большей частью вашего кода, но я думаю, что уловил суть вопроса, не захватывая полностью код.

Другим решением является создание объектов компаратора в качестве подклассов из базового класса компаратора, а затем вызов функции сравнения объекта, но вы упоминаете, что пытаетесь оставаться структурированным вместо ОО.

...