Dictionary 在空字典Delphi 10.4上迭代时出现问题

Dictionary 在空字典Delphi 10.4上迭代时出现问题,dictionary,delphi,iteration,Dictionary,Delphi,Iteration,我有以下代码和两个字典。我可以看到,当我迭代DictToAdd.remove时,即使它是空的,执行流也会进入循环,因此DictToAdd.remove(一个整数);以 整数的旧值 var DictForbidden, DictToAdd : TDictionary<Integer,boolean>; var anInteger: Integer; DictForbidden := TDictionary<Integer,boolean>.Create; D

我有以下代码和两个字典。我可以看到,当我迭代DictToAdd.remove时,即使它是空的,执行流也会进入循环,因此DictToAdd.remove(一个整数);以 整数的旧值

var DictForbidden, DictToAdd : TDictionary<Integer,boolean>; 
var anInteger: Integer;
    
DictForbidden   := TDictionary<Integer,boolean>.Create;
DictToAdd       := TDictionary<Integer,boolean>.Create;
    
anInteger := 1;
DictToAdd.Add(anInteger,true);
    
for anInteger in DictForbidden.Keys do
  DictToAdd.remove(anInteger);
    
DictForbidden.Free;
DictToAdd.Free; 
var dictoblimited,DictToAdd:t字典;
var a整数:整数;
DictForbidden:=t字典。创建;
DictToAdd:=t字典。创建;
整数:=1;
DictToAdd.Add(整数,true);
对于一个听写员来说是禁止的。钥匙可以
口述添加、删除(整合器);
禁止。免费;
自由口述;
我正在运行Delphi10.4,我不记得10.3中有这样的行为。我想当时如果字典是空的,循环就不会被输入。你知道这是Delphi10.4上的新功能吗?或者我在这里做错了什么


尊敬的Carlos,在我的10.4.1中,它没有进入循环。但是,由于编译器进行了优化,在调试跟踪时可能会出现这种情况。试着换一个新的

DictToAdd.Remove
带着

writeln(anInteger) // if Console Application
ShowMessage(IntToStr(anInteger)) // if GUI Application

查看是否有任何报告。

非常感谢您的快速帮助

事实上,你是对的。循环之后,DictToAdd仍然包含1。因此,这里基本上没有比在DictToAdd.remove(一个整数)行中放置断点更好的情况;停止执行,然后将光标放在一个整数上,您看到的值是1,但跨过1的步骤不会被删除。当用showmessage替换移除时,我观察到同样的情况,即达到断点,但showmessage未执行

还注意到当使用像这样的开始/结束

for anInteger in DictForbidden.Keys do
begin
  DictToAdd.remove(anInteger);
end;

未达到断点。

这是调试器的一个小麻烦,因为循环当然会生成一些可执行代码,尤其是for in循环,该循环调用了
MoveNext
Current
,并在完成后为枚举数生成了一些清理代码

这段代码必须放在某个地方,调试器(也称为“蓝点”)使用的代码行信息通常与您编写的实际代码重叠,就像在本例中一样

为了说明这一点,这里是我将代码放入控制台应用程序时反汇编的样子

如您所见,这里显示了两个断点,它们属于我在第21行中放置的同一个断点。但是被击中的是一个带有清除代码的人,该代码负责销毁枚举器。如果您点击F7并使用debug DCU进行编译,您会注意到它实际上并没有进入
TDictionary.Remove
,而是进入
TObject.Destroy

现在,放置
开始
结束
后的反汇编:


再次显示了两个断点,但这次我自己实际放置了两个断点-它们用于不同的行。

您没有做错任何事情,这在我的10.3版上可以正常工作。目前无法访问10.4。您是否绝对确定实际调用了
Remove
?如果将
ShowMessage(DictToAdd.Count.ToString)
放在循环之后、清理之前,会发生什么情况?@AndreasRejbrand:在任何情况下,它都可能报告1,因为无法保证(即使它循环一次)它将删除值1-它可能(如果编译器中有错误)以任意随机值与整数循环一次。最好在循环中包含一个“visible”语句,以查看循环的内部部分是否正在执行…@HeartWare:Correct,my bad。在列表中迭代时删除一个项会给迭代器带来一些麻烦。我建议使用反向for循环,这样您可以使用for向下迭代或编写while循环。记住接受回答您的问题的答案和/或您认为有用的向上投票的答案。