List index out of bounds whilst deleting items

不问归期 提交于 2019-12-01 06:18:57

问题


I solved my problem but I need to know why this problem raised to me ?!

I write a project that load file to listBox then delete the strings one by one,

but when I delete listBox strings this exception raised to me!

list index out of bounds (5) !

I type this for loop to read list box and delete strings:

for i := 0 to ListBox3.Count -1  do
  begin
      ShowMessage(ListBox3.Items[i]);
       ListBox3.items.Delete(i);
  end;

and my problem solved by do a little change in for-loop statement

for i := ListBox3.Items.Count - 1 downto 0 do
  begin
      ShowMessage(ListBox3.Items[i]);
       ListBox3.items.Delete(i);
  end;

Why the first statement raised an exception, and the second one work fine ?


回答1:


By deleting items moving forward, you're cutting the branch off that you're standing on. :-) The upper bounds of the loop is only evaluated once, before the loop begins, and if you delete items there are now fewer in the list than there were when the bound was calculated.

  • Loop limit is evaluated (for example, List.Count - 1 = 5). Valid indexes into it are [0..4]
  • The loop starts, and you retrieve List[0] and delete it. List Count = 4, bounds is still 5
  • The index is incremented, you retrieve and delete List[1]. List Count = 3, bounds is still 5
  • The index is incremented, you retrieve and delete List[2]. List Count = 2, bounds is still 5.
  • The index is incremented, you retrieve List[3] - Oops! There are only 2 items in the list, now at indexes [0..1] - List index out of bounds(3).

By iterating backwards, even though the bounds is still only calculated at the beginning, you're removing the items from the end and decrementing the count at the same time.

  • Bounds is 5, and you retrieve List[4] and delete it. Count is now 4, bounds is still 5
  • Index is decremented, and you retrieve List[3] and delete it. Count is now 3, bounds is still 5
  • Index is decremented, and you retrieve List[2] and delete it. Count is now 2, bounds is still 5.
  • Index is decremented, and you retrieve and delete List[1]. Count is now 1, bounds is still 5.
  • Index is decremented, and you retrieve and delete List[0]. List is now empty, but we've reached the terminating condition of the loop (downto 0) and the loop exits safely.



回答2:


Each time you delete an item from the list, the list contains one less item. However, the for statement copies the list count at the beginning, and is not updated upon each iteration. Therefore, by the time you get halfway through the list, the counter i becomes larger than the current (new) list count, even though the list no longer contains the original number of items.

As an alternative, you could also do a loop like this:

while ListBox3.Items.Count > 0 do begin
  ShowMessage(ListBox3.Items[0]);
  ListBox3.items.Delete(0);
end;



回答3:


There may be situation when you DO NOT delete certain items. Then the generic approach would be

i := 0;
while i < ListBox3.Items.Count do
  begin
    ShowMessage(ListBox3.Items[i]);
    if <wantToDelete> then // some condition there
      ListBox3.Items.Delete(i)
    else
      Inc(i);
   end;


来源:https://stackoverflow.com/questions/36375571/list-index-out-of-bounds-whilst-deleting-items

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!