我需要释放GetEnumerator返回的枚举器吗?

7
我希望用 Delphi XE2 中的枚举器来处理通用集合。我想知道函数GetEnumerator返回的TEnumerator由谁拥有(文档中没有明确说明):
  • 我自己拥有它,需要在使用后将其释放吗?
  • 还是它由集合拥有,我不必关心释放它?

代码:

procedure Test;
var
  myDictionary: TDictionary<String, String>;
  myEnum: TDictionary<String, String>.TPairEnumerator;
begin
  { Create a dictionary }
  myDictionary := TDictionary<String, String>.Create;
  myDictionary.Add('Key1', 'Value 1');
  myDictionary.Add('Key2', 'Value 2');

  { Use an enumerator }
  myEnum := myDictionary.GetEnumerator;
  // ... do something with the Enumerator ...

  { Release objects }
  myEnum.Free; // ** Do I need to free the enumerator? **
  myDictionary.Free;          
end;

2
你可以在工程源码的begin之后加上"ReportMemoryLeaksOnShutdown := True"来测试,这样你就能够测试多种不同的泄露情况。 - user497849
1
@DorinDuminica ReportMemoryLeaksOnShutdown := True 即使不是第一行也有效 - mjn
@mjn 谢谢,我忘记编辑它了,在写完上面的评论后,我在某个地方(记不清了)读到可以在代码的任何部分更改标志,但仍然最好将其放在“易于访问”的某个位置,而无需在文件中搜索... - user497849
1个回答

6
如果您查看TDictionary的源代码,您会发现GetEnumerator(在其祖先类中)调用DoGetEnumerator,而在TDictionary中调用重新引入的版本GetEnumerator。
重新引入的TDictionary.GetEnumerator创建一个TPairEnumerator实例,将自身作为要枚举的字典传递。该字典不持有对TPairEnumerator的引用。PairEnumerator不会被通知其所枚举的字典已被销毁。
因此,是的,您需要自己释放枚举器,并且为了避免任何访问冲突,您确实应该在销毁其所枚举的字典之前这样做。

如果使用for-in循环,我们无法引用枚举器(它是隐藏的); Delphi是否会自动释放它? - teran
3
@teran:是的,编译器会添加必要的代码来释放隐藏的枚举变量。 - Uwe Raabe
@UweRaabe,是的,我刚刚检查过了 :) 我认为for-in循环将枚举器存储为对IEnumerable的引用(我想它创建了一个新对象,支持IEnumerable<>并拥有我们的枚举器对象,所以它在循环结束时销毁了我们的枚举器。因此,Embarcadero建议实现IEnumerable使容器可枚举-http://docwiki.embarcadero.com/Libraries/en/System.IEnumerable) - teran
我在我的示例中更改了发布顺序,现在与您建议的顺序相同! - Name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接