1

我有一段这样的代码:

for I := 0 to Self.EventQueue.Count do
    Dispose(Self.EventQueue[I]);

当 Count 为 0 时它会出错,因为它会尝试Dispose不存在的元素。当我将其更改为

for I := 0 to Self.EventQueue.Count-1 do
    Dispose(Self.EventQueue[I]);

一切正常。有什么优雅的方法可以解决这个问题,或者这是常见的做法吗?

4

3 回答 3

0

我的天啊。那是因为在从 0 到 Self.EventQueue.Count 的循环中,您会遍历 Self.EventQueue.Count + 1 个项目。

于 2013-04-13T20:28:06.040 回答
0

这是绝对正常的行为,并且记录在 Delphi/FreePascal 中每个列表和容器类的帮助中。原因很清楚 - 如果列表中有三个项目,并且第一个项目位于 index 0,那么你有项目0, 1, 2但 a Countof 3,对吗?

for i := 0 to StringList.Count - 1 do  // TStringList

for i := 0 to List.Count - 1 do        // TList

for i := 0 to StringGrid1.ColCount do  // TStringGrid

替代方案不是很清楚(对我来说打字更糟糕):

for i := 0 to Pred(StringList.Count) do  

动态数组0也从索引开始。

var
  IntArray: array of Integer;
  i: Integer;
begin
  SetLength(IntArray, 10);
  for i := Low(IntArray) to High(IntArray) do  // loop is 0..9
    //
end;

唯一不0基于 FPC/Delphi 的是字符串类型,以 开头1,以及非动态数组(在代码中以固定大小声明的数组),它们几乎可以从您想要的任何索引开始。例如,这是完全合法的:

var
  IntArray: array[-10..10] of Integer;
  i: Integer;
begin
  for i := Low(IntArray) to High(IntArray) do // loop is -10..10
    //
end;

顺便说一句,每当您在循环中执行任何会减少列表中项目数量的操作时,您都应该向后迭代:

for i := List.Count - 1 downto 0 do

否则,您将在列表末尾进行迭代,因为Count仅在循环开始时才评估 。

于 2013-04-13T20:28:47.587 回答
0

我更喜欢使用

for I := 1 to Self.EventQueue.Count do
  Dispose(Self.EventQueue[I-1]);

这样很明显,如果计数为零并且索引的更正发生在重要的地方,则不会发生任何事情

于 2016-03-29T21:33:42.753 回答