Delphi: Goto не считается вредным в этом случае? - PullRequest
4 голосов
/ 17 октября 2010

Хорошо, у вас есть экземпляр TObjectList.Вы хотите просмотреть все элементы в нем и удалить некоторые объекты из списка.Вы не можете сделать это:

for I := 0 to ObjectList.Count - 1 do
  if TMyClass(ObjectList[I]).ShouldRemove then
    ObjectList.Delete(I);

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

Итак, вот мое решение:

Again:
  for I := 0 to ObjectList.Count - 1 do
    if TMyClass(ObjectList[I]).ShouldRemove then
    begin
      ObjectList.Delete(I);
      goto Again;
    end;

Это лучшее решение, которое я нашел до сих пор.Если у кого-нибудь есть более подходящее решение, я бы с удовольствием посмотрел его.

Ответы [ 3 ]

30 голосов
/ 17 октября 2010

Попробуйте вместо этого:

 for I := ObjectList.Count - 1 downto 0 do
   if TMyClass(ObjectList[I]).ShouldRemove then
     ObjectList.Delete(I);

Это выглядит как особенно плохое использование goto, выпрыгивая из цикла for таким образом.Я предполагаю, что это работает (так как вы используете это), но это даст мне волю.

7 голосов
/ 17 октября 2010

Вы также можете использовать

  I := 0;
  while I < ObjectList.Count do begin
    if TMyClass(ObjectList[I]).ShouldRemove then ObjectList.Delete(I)
    else Inc(I);
  end;
0 голосов
/ 17 октября 2010

Единственное действительное использование Goto, которое я видел, - это то, которое предоставляется в помощь Delphi.

for I := 0 to something do
begin
  for J := 0 to something do
  begin
    For K := 0 to something do
    begin
      if SomeCondition then
        Goto NestedBreak
    end;
  end;
end;
NestedBreak:

Хотя Goto можно было бы избежать в этом примере, переместив цикл в локальную функцию и используя EXIT, например. Если подфункция неприемлема, вы все равно можете сделать это:

for I := 0 to something do
begin
  for J := 0 to something do
  begin
    For K := 0 to something do
    begin
      if SomeCondition then
      begin
        GottaBreak := True
        Break;
      end; 
    end;
    if GottaBreak then Break;
  end;
  if GottaBreak then Break;
end;

Это чуть менее оптимально.

Мне еще предстоит увидеть еще одну ситуацию, когда Гото было бы лучшим решением (или вообще каким-либо хорошим).

Гото само по себе не плохо. Это команда управления потоком, такая же, как EXIT, BREAK или CONTINUE. За исключением того, что другие ограничены конкретными ситуациями и управляются компилятором правильно. (Учитывая сказанное, некоторые программисты, с которыми я говорил, считают, что они столь же вредны, как и Гото, мнение, которое я не разделяю) Гото не ограничен, то, что вы можете с ним сделать, может иметь очень негативные последствия. Во всяком случае, я думаю, что я уже вышел за рамки вопроса. ^ _ ^

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