Вы можете сделать это
var results = data.GroupBy(x => new { x.ApprovalStatus, x.Id })
.Select(x => new
{
ApprovalStatus = x.Key.ApprovalStatus,
Id = x.Key.Id,
Count = x.Count()
});
Используйте интерфейсы вместо объектов. Они - ссылка, считаемая и освобожденная автоматически, когда подсчет ссылок достигает 0.
Я записал функциональный 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 со встроенной сборкой "мусора" в ближайшем будущем я увлекаются использованием этого краткого метода легкого освобождения локальных временных объектов!:)
Вроде интерфейсов можно попробовать 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
владение объекта. Если исключение происходит, прежде чем это происходит, то, поскольку стек раскручивается, и интерфейс выпущен, защита освободит объект.
Я должен сказать, мне не нравится "скрывать" Свободный из объекта. Намного лучше иметь традиционный код:
MyObject := TObject.Create;
try
// do stuff
finally
FreeAndNil(MyObject);
end;
Никаким путем это не может пойти не так, как надо, работы как ожидалось, и люди распознают шаблон.
Используйте монопольное использование объекта компонентов, которые обеспечивает VCL. Пока Вы создаете объекты с ненулевым владельцем, Вы не должны освобождать их explicitely. См. также мой ответ на этот вопрос.
Вот является API для Сборщика "мусора" Boehm DLL для Delphi. API Delphi записан Barry Kelly, который работает на CodeGear, пишущий компилятор теперь.
При использовании Delphi для .NET / Призма Delphi, Вы получаете Сборку "мусора", которая заботится обо всем освобождении.
Интеллектуальные указатели работают действительно хорошо, если у Вас есть Delphi 2009.