好的,所以你有一个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;
这是迄今为止我发现的最佳解决方案。如果有人有一个更整洁的解决方案,我很乐意看到它。
答案 0 :(得分:30)
请改为尝试:
for I := ObjectList.Count - 1 downto 0 do
if TMyClass(ObjectList[I]).ShouldRemove then
ObjectList.Delete(I);
这看起来像是一个特别糟糕的使用goto,跳出了那样的for循环。我认为它有效(因为你正在使用它),但它会给我一些意志。
答案 1 :(得分:7)
您也可以使用
I := 0;
while I < ObjectList.Count do begin
if TMyClass(ObjectList[I]).ShouldRemove then ObjectList.Delete(I)
else Inc(I);
end;
答案 2 :(得分:0)
我见过的唯一有效使用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:
虽然可以通过在本地函数中移动循环并使用EXIT来避免Goto,例如。如果不接受子功能,您仍然可以这样做:
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;
这只是不太理想。
我还没有看到其他情况,其中Goto是最佳解决方案。(或任何好处)。
转到本身并不错。这是一个流程控制命令,就像EXIT,BREAK或CONTINUE一样。除了那些其他仅限于特定情况并由编译器正确管理。 (话虽如此,我与之谈过的一些程序员认为那些与Goto一样有害,我不同意的观点)转到不受限制,你可以用它做的事情会产生非常负面的影响。无论如何,我认为我已经超出了问题的范围。 ^ _ ^