我有一段这样的代码:
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]);
一切正常。有什么优雅的方法可以解决这个问题,或者这是常见的做法吗?
我的天啊。那是因为在从 0 到 Self.EventQueue.Count 的循环中,您会遍历 Self.EventQueue.Count + 1 个项目。
这是绝对正常的行为,并且记录在 Delphi/FreePascal 中每个列表和容器类的帮助中。原因很清楚 - 如果列表中有三个项目,并且第一个项目位于 index 0
,那么你有项目0, 1, 2
但 a Count
of 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
仅在循环开始时才评估 。
我更喜欢使用
for I := 1 to Self.EventQueue.Count do
Dispose(Self.EventQueue[I-1]);
这样很明显,如果计数为零并且索引的更正发生在重要的地方,则不会发生任何事情