Как автоматически освободить классы/объекты?

Вы можете сделать это

var results = data.GroupBy(x => new { x.ApprovalStatus, x.Id })
                  .Select(x => new
                         {
                            ApprovalStatus = x.Key.ApprovalStatus,
                            Id = x.Key.Id,
                            Count = x.Count()
                         });
12
задан Shannon 6 January 2009 в 09:52
поделиться

8 ответов

Используйте интерфейсы вместо объектов. Они - ссылка, считаемая и освобожденная автоматически, когда подсчет ссылок достигает 0.

19
ответ дан 2 December 2019 в 03:08
поделиться

Я записал функциональный GC (obj: TObject) (для Собирают "мусор"), который берет объект и освобождает его, когда выполнение оставляет существующий метод. Это отчасти похоже на короткую краткую функцию для Попытки Наконец Свободный блок.

Вместо:

procedure Test;
var AQuery: TQuery;
begin
  AQuery := TQuery.Create(nil);
  try
    ...
  finally
    FreeAndNil(AQuery);
  end;
end;

Я просто имею:

procedure Test;
var AQuery: TQuery;
begin
  AQuery := TQuery.Create(nil);
  GC(AQuery);
  ...
end;

Функция GC просто возвращает объект в форме интерфейса.

function GC(obj: TObject): IGarbo;
begin
  Result := TGarbo.Create(obj);
end;

Поскольку класс TGarbo убывает от TInterfacedObject, когда объект TGarbo выйдет из объема, он будет автоматически освобожден. В деструкторе объекта TGarbo это также освобождает объект, в котором Вы передали ему, он - конструктор (объект, который Вы передали в функции GC).

type
  IGarbo = interface
    ['{A6E17957-C233-4433-BCBD-3B53C0C2C596}']
    function Obj: TObject;
  end;

  TGarbo = class(TInterfacedObject, IGarbo)
  private
    FObj: TObject;
  public
    constructor Create(AObjectToGC: TObject);
    destructor Destroy; override;
    function Obj: TObject;
  end;

{ TGarbo }

constructor TGarbo.Create(AObjectToGC: TObject);
begin
  inherited Create;
  FObj := AObjectToGC;
end;

destructor TGarbo.Destroy;
begin
  if Assigned(FObj) then
    FreeAndNil(FObj);
  inherited;
end;

function TGarbo.Obj: TObject;
begin
  Result := FObj;
end;

При застревании в мире Delphi 7 без вида обновления до версии Delphi со встроенной сборкой "мусора" в ближайшем будущем я увлекаются использованием этого краткого метода легкого освобождения локальных временных объектов!:)

13
ответ дан 2 December 2019 в 03:08
поделиться

Вроде интерфейсов можно попробовать Guard функция в JclSysUtils единица, часть свободной Библиотеки Кода джедая. Это позволяет Вам связывать объект с отдельной интерфейсной ссылкой, поэтому когда та интерфейсная ссылка уничтожается, объект уничтожается наряду с ним. Это может быть полезно, когда у Вас нет опции изменения классов, Вы используете, чтобы заставить их поддерживать собственные интерфейсы.

var
  G: ISafeGuard;
  foo: TStrings;
begin
  // Guard returns TObject, so a type-cast is necessary
  foo := Guard(TStringList.Create, G) as TStrings;
  // Use the object as normal
  foo.Add('bar');
end; // foo gets freed automatically as G goes out of scope

Существуют перегрузки для объектов и GetMem- выделенные указатели. Существует также IMultiSafeGuard, который может гарантировать, что освобождены несколько объектов.

Если у Вас есть функция фабрики, Вы могли бы создавать объект, устанавливая некоторые его свойства, и затем возвращая ее. Если исключение произойдет при установке свойств, то Вы захотите удостовериться, что Вы освобождаете объект, так как Вы не можете возвратить его. Один способ сделать, который похож на это:

function Slurp(const source: TFileName): TStrings;
begin
  Result := TStringList.Create;
  try
    Result.LoadFromFile(source);
  except
    Result.Free;
    raise;
  end;
end;

С Guard, это стало бы этим:

function Slurp(const source: TFileName): TStrings;
var
  G: ISafeGuard;
begin
  Result := Guard(TStringList.Create, G) as TStrings;
  Result.LoadFromFile(source);
  G.ReleaseItem;
end;

ReleaseItem метод отменяет ISafeGuardвладение объекта. Если исключение происходит, прежде чем это происходит, то, поскольку стек раскручивается, и интерфейс выпущен, защита освободит объект.

7
ответ дан 2 December 2019 в 03:08
поделиться

Я должен сказать, мне не нравится "скрывать" Свободный из объекта. Намного лучше иметь традиционный код:

MyObject := TObject.Create;
try
  // do stuff
finally
  FreeAndNil(MyObject);
end;

Никаким путем это не может пойти не так, как надо, работы как ожидалось, и люди распознают шаблон.

6
ответ дан 2 December 2019 в 03:08
поделиться

Используйте монопольное использование объекта компонентов, которые обеспечивает VCL. Пока Вы создаете объекты с ненулевым владельцем, Вы не должны освобождать их explicitely. См. также мой ответ на этот вопрос.

5
ответ дан 2 December 2019 в 03:08
поделиться

Вот является API для Сборщика "мусора" Boehm DLL для Delphi. API Delphi записан Barry Kelly, который работает на CodeGear, пишущий компилятор теперь.

2
ответ дан 2 December 2019 в 03:08
поделиться

При использовании Delphi для .NET / Призма Delphi, Вы получаете Сборку "мусора", которая заботится обо всем освобождении.

-2
ответ дан 2 December 2019 в 03:08
поделиться

Интеллектуальные указатели работают действительно хорошо, если у Вас есть Delphi 2009.

1
ответ дан 2 December 2019 в 03:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: