Реализация списка с записями - PullRequest
4 голосов
/ 16 декабря 2011

Дополнительный вопрос к этому вопросу : (обратите внимание, что это не дубликат, я прошу альтернативы здесь).

Есть ли способ заставить следующую работу:

type
  List <T> = record
  private
    FList  : TList <T>;
    FGuard : IInterface,
    procedure CheckCreated;
  public
    procedure Add(const Value : T);
  end;

procedure List <T>.CheckCreated;
begin
if (FGuard = nil) then
  begin
  FList := TList <T>.Create;
  FGuard := TGuard.Create (FList);    // guard calls free on list in destructor
  end;
end;

procedure List <T>.Add (const Value : T);
begin
CheckCreated;
FList.Add (Value);
end;

В идеале я хочу использовать это так:

function ReturnHandles : List <THandle>;
begin
Result.Add (2);
Result.Add (3);
end;

Как объяснено в ответах на связанный вопрос, это не работает (что на самом деле жалко). Он не будет создавать новый список при каждом вызове.

К сожалению, это тоже не работает:

function ReturnHandles : List <THandle>;
begin
Initialize (Result);
Result.Add (2);
Result.Add (3);
end;

Утечка из интерфейсов защиты и всех списков, потому что Initialize просто перезаписывает ссылку на интерфейс, не уменьшая счетчик ссылок.

Есть ли способ заставить эту работу? Или вы бы предложили сделать этот интерфейс вместо записи и просто жить со строительными линиями?

function ReturnHandles : List <THandle>;
begin
Result := List <T>.Create;
Result.Add (2);
Result.Add (3);   
end;

Спасибо за вашу помощь!

1 Ответ

2 голосов
/ 16 декабря 2011

Это должно работать нормально, если я вас правильно понимаю:

function ReturnHandles : List <THandle>;
begin
  Finalize(Result);
  Result.Add (2);
  Result.Add (3);
end;

Вызов Finalize гарантирует, что для всех управляемых типов установлено значение nil, которое, как я считаю, является вашим намерением.

Этот вопрос очень тесно связан с вашим предыдущим вопросом, и я думаю, что вы могли бы использовать out параметры для упрощения кода.Результат функции неявно является параметром var, но если вы использовали явный параметр out, он будет инициализировать управляемые типы по вашему желанию.

procedure InitializeHandles(out Handles : List <THandle>);
begin
  Handles.Add (2);
  Handles.Add (3);
end;

Лично, поскольку вы вводите интерфейс вмикс, я думаю, я был бы склонен пройти весь путь и использовать исключительно интерфейсы.Или используйте стандартные классы и примите необходимость управления жизненным циклом try / finally.

...