I have the following code:
program Tlist;
{$APPTYPE CONSOLE}
{$R *.res}
uses
madExcept,
madLinkDisAsm,
madListHardware,
madListProcesses,
madListModules,
System.Generics.Collections,
System.SysUtils;
type
TMyItem = class(TInterfacedObject)
private
ItemPrice: Currency;
public
constructor Create(const aItemPrice: Currency); reintroduce;
end;
IMyList = interface
['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
function Reset(const aItems: Integer): Integer;
function Add(const aPrice, aItemN: Integer): Integer;
end;
TMyList = class(TInterfacedObject, IMyList)
private
FList: array of TList<TMyItem>;
public
function Reset(const aItems: Integer): Integer;
function Add(const aPrice, aItemN: Integer): Integer;
end;
{ TMyList }
function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
FList[aItemN].Add(TMyItem.Create(aPrice));
Result := FList[aItemN].Count;
end;
function TMyList.Reset(const aItems: Integer): Integer;
var
I: Integer;
begin
SetLength(FList, 0);
SetLength(FList, aItems);
for I := 0 to Length(FList) - 1 do
begin
FList[I] := TList<TMyItem>.Create;
end;
Result := Length(FList);
end;
{ TMyItem }
constructor TMyItem.Create(const aItemPrice: Currency);
begin
ItemPrice := aItemPrice;
end;
var
MyList: IMyList;
begin
MyList := TMyList.Create;
MyList.Reset(3);
mylist.Add(1000, 1);
end.
When executed, it throws an exception linked to TList<T>.
As TList implements the reference counting and all the classes are derived from TInterfacedObject I was under the impression that the memory would be released automatically but obviously, I am wrong.
What am I doing wrong?
EDIT
Following the suggestions I came up with the following code:
program Tlist2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
madExcept,
madLinkDisAsm,
madListHardware,
madListProcesses,
madListModules,
System.Generics.Collections,
System.SysUtils;
type
IMyItem = interface
['{2EB53CC3-E5FC-474B-A162-30BBD2D17C48}']
end;
TMyItem = class(TInterfacedObject, IMyItem )
private
ItemPrice: Currency;
public
constructor Create(const aItemPrice: Currency); reintroduce;
end;
IMyList = interface
['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
function Reset(const aItems: Integer): Integer;
function Add(const aPrice, aItemN: Integer): Integer;
end;
TMyList = class(TInterfacedObject, IMyList)
private
FList: array of TList<TMyItem>;
public
function Reset(const aItems: Integer): Integer;
function Add(const aPrice, aItemN: Integer): Integer;
destructor Destroy; override;
end;
{ TMyList }
function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
FList[aItemN].Add(TMyItem.Create(aPrice));
Result := FList[aItemN].Count;
end;
destructor TMyList.Destroy;
var
I: Integer;
a: Integer;
begin
for I := 0 to Length(FList) - 1 do
begin
if FList[I].Count > 0 then
begin
for a := 0 to FList[I].Count - 1 do
begin
FList[I][a].Destroy
end;
end;
FList[I].Destroy;
end;
inherited;
end;
function TMyList.Reset(const aItems: Integer): Integer;
var
I: Integer;
begin
SetLength(FList, 0);
SetLength(FList, aItems);
for I := 0 to Length(FList) - 1 do
begin
FList[I] := TList<TMyItem>.Create;
end;
Result := Length(FList);
end;
{ TMyItem }
constructor TMyItem.Create(const aItemPrice: Currency);
begin
ItemPrice := aItemPrice;
end;
var
MyList: IMyList;
begin
MyList := TMyList.Create;
MyList.Reset(3);
mylist.Add(1000, 1);
end.
That works fine, no more memory leaks BUT I am under the impression that I am missing out on something here.
I thought that by using interfaces and deriving my classes from TInterfacedObject the destroyer would not be necessary.
Following the input from David and Remi I have amended my code:
No memory leaks.