Нужно ли освобождать перечислитель, возвращаемый GetEnumerator?

Я хочу использовать перечислитель для универсальной коллекции с Delphi XE2. Мне интересно, кому принадлежит TEnumerator, возвращаемый функцией GetEnumerator (в документации я не нашел четкого ответа):

  • Являюсь ли он владельцем и должен ли я освобождать его после использования?
  • Или он принадлежит коллекции, и мне не нужно заботиться о его выпуске?

Код:

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;

person Name    schedule 15.03.2012    source источник
comment
вы также можете проверить это, добавив ReportMemoryLeaksOnShutdown := True в качестве первой строки после начала в исходном коде вашего проекта, таким образом вы можете проверить различные другие утечки.   -  person    schedule 15.03.2012
comment
@DorinDuminica ReportMemoryLeaksOnShutdown := True также работает, если это не первый линия   -  person mjn    schedule 19.03.2012
comment
@mjn спасибо, я забыл отредактировать его, после того, как написал комментарий выше, я где-то читал (не могу вспомнить), что можно изменить флаг в любой части кода, но все же это хорошая идея иметь он где-то легко доступен без поиска в файлах...   -  person    schedule 19.03.2012


Ответы (1)


Если вы посмотрите на источник TDictionary, вы обнаружите, что GetEnumerator (в своем предке) вызывает DoGetEnumerator, который в TDictionary вызывает повторно введенную версию GetEnumerator.

Вновь введенный TDictionary.GetEnumerator создает экземпляр TPairEnumerator, передавая себя в качестве перечисляемого словаря. В словаре нет ссылки на TPairEnumerator. PairEnumerator не получает уведомления об уничтожении своего словаря.

Итак, да, вам нужно освободить перечислитель самостоятельно, и во избежание каких-либо нарушений прав доступа вы действительно должны сделать это до уничтожения словаря, который он перечисляет.

person Marjan Venema    schedule 15.03.2012
comment
в случае использования цикла for-in у нас нет ссылки на перечислитель (он скрыт); Delphi сама освобождает его? - person teran; 15.03.2012
comment
@teran: да, компилятор добавляет необходимую магию, чтобы освободить скрытый перечислитель. - person Uwe Raabe; 15.03.2012
comment
@UweRaabe, да, я только что проверил :) действительно я думаю, что цикл for-in хранит перечислитель как ссылку на IEnumerable (я полагаю, он создает новый объект, который поддерживает IEnumerable<> и владеет нашим объектом перечислителя, поэтому он уничтожает наш перечислитель в конце цикла . по этой причине Embarcadero рекомендует реализовать IEnumerable, чтобы сделать контейнеры перечисляемыми — docwiki.embarcadero.com /Libraries/en/System.IEnumerable) - person teran; 15.03.2012
comment
Я изменил порядок выпуска в своем примере, чтобы он был в том же порядке, как вы предложили! - person Name; 19.03.2012