delphi 释放对象时失去价值
delphi lose value when freeing object
抱歉,如果我有同样的问题。
在 Delphi 中,我的功能是这样的:
function TModuleDatabase.LoadCountryList():TDictionary<integer, String>;
var
UQ: TUniQuery;
UC: TUniConnection;
CountryList: TDictionary<integer, String>;
begin
CountryList := TDictionary<integer, String>.Create;
UC := UniConnection2;
UQ := TUniQuery.Create(nil);
try
UQ.Connection := UC;
try
UQ.SQL.Clear;
UQ.SQL.Add('SELECT ID,NAME FROM COUNTRY ORDER BY NAME ASC');
UQ.Open;
while not UQ.Eof do
begin
CountryList.Add(UQ.Fields.FieldByName('ID').AsInteger,UQ.Fields.FieldByName('NAME').AsString);
UQ.Next;
end;
Result := CountryList;
except
on E:Exception do
ModuleMsgDialog.WarningMsg(E.Message);
end;
finally
UQ.Close;
UQ.Free;
CountryList.Free;
end;
end;
我将函数分离到其他DataModule,这样我就不会在每个表单中每次都重复这个函数。但是当我从一个表单中调用这个函数时:
procedure TCompanyDetailsForm.FormCreate(Sender: TObject);
var
i: Integer;
sItem: String;
CountryList: TDictionary<integer, String>;
begin
PageControl1.ActivePage := AddressTab;
CountryList := ModuleDatabase.LoadCountryList();
for i in CountryList.Keys do
begin
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
end;
end;
问题出在 CountryList.Free;。字典中的所有项目在使用前都已释放。
如果我不做free,会造成内存泄漏。
如何在做免费之前传输数据的最佳方式。或者如何在调用后以其他形式或单元释放价值。
感谢您的帮助。
您有两个主要选择。
选项 1 – 调用方提供实例化对象
在这里你让来电者终身负责。调用者传入实例化对象,被调用者填充它。
procedure PopulateCountryDict(Countries: TDictionary<Integer, string>);
begin
// populate Countries here
end;
选项 2 – 调用方 returns 一个新实例化的对象,它也被填充
这是可行的,但调用者必须承担被调用者生命周期的责任returns。它看起来像这样:
function CreateAndPopulateCountryDict: TDictionary<Integer, string>;
begin
Result := TDictionary<Integer, string>.Create;
try
// populate Result here
except
Result.Free; // until this function returns, we are responsible for lifetime
raise;
end;
end;
调用代码如下所示:
var
Countries: TDictionary<Integer, string>
....
Countries := CreateAndPopulateCountryDict;
try
// do stuff with Countries
finally
Countries.Free;
end;
你应该在Form Create方法中创建字典,在你需要的地方销毁或清除。不在 LoadCountryList 函数中。
作为 David 回答的扩展,还有另一个使用回调的选项
procedure LoadCountryList( ACallback : TProc<TDictionary<integer,string>> );
var
LCountryList : TDictionary<integer,string>;
begin
// create the instance
LCountryList := TDictionary<integer,string>.Create;
try
// fill the dictionary
// execute the callback
ACallback( LCountryList );
finally
// free the instance
LCountryList.Free;
end;
end;
然后在您的代码中使用它
procedure TCompanyDetailsForm.FormCreate(Sender: TObject);
begin
PageControl1.ActivePage := AddressTab;
LoadCountryList(
procedure ( CountryList : TDictionary<integer,string> )
var
i: Integer;
begin
for i in CountryList.Keys do
begin
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
end;
end );
end;
抱歉,如果我有同样的问题。
在 Delphi 中,我的功能是这样的:
function TModuleDatabase.LoadCountryList():TDictionary<integer, String>;
var
UQ: TUniQuery;
UC: TUniConnection;
CountryList: TDictionary<integer, String>;
begin
CountryList := TDictionary<integer, String>.Create;
UC := UniConnection2;
UQ := TUniQuery.Create(nil);
try
UQ.Connection := UC;
try
UQ.SQL.Clear;
UQ.SQL.Add('SELECT ID,NAME FROM COUNTRY ORDER BY NAME ASC');
UQ.Open;
while not UQ.Eof do
begin
CountryList.Add(UQ.Fields.FieldByName('ID').AsInteger,UQ.Fields.FieldByName('NAME').AsString);
UQ.Next;
end;
Result := CountryList;
except
on E:Exception do
ModuleMsgDialog.WarningMsg(E.Message);
end;
finally
UQ.Close;
UQ.Free;
CountryList.Free;
end;
end;
我将函数分离到其他DataModule,这样我就不会在每个表单中每次都重复这个函数。但是当我从一个表单中调用这个函数时:
procedure TCompanyDetailsForm.FormCreate(Sender: TObject);
var
i: Integer;
sItem: String;
CountryList: TDictionary<integer, String>;
begin
PageControl1.ActivePage := AddressTab;
CountryList := ModuleDatabase.LoadCountryList();
for i in CountryList.Keys do
begin
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
end;
end;
问题出在 CountryList.Free;。字典中的所有项目在使用前都已释放。 如果我不做free,会造成内存泄漏。
如何在做免费之前传输数据的最佳方式。或者如何在调用后以其他形式或单元释放价值。
感谢您的帮助。
您有两个主要选择。
选项 1 – 调用方提供实例化对象
在这里你让来电者终身负责。调用者传入实例化对象,被调用者填充它。
procedure PopulateCountryDict(Countries: TDictionary<Integer, string>);
begin
// populate Countries here
end;
选项 2 – 调用方 returns 一个新实例化的对象,它也被填充
这是可行的,但调用者必须承担被调用者生命周期的责任returns。它看起来像这样:
function CreateAndPopulateCountryDict: TDictionary<Integer, string>;
begin
Result := TDictionary<Integer, string>.Create;
try
// populate Result here
except
Result.Free; // until this function returns, we are responsible for lifetime
raise;
end;
end;
调用代码如下所示:
var
Countries: TDictionary<Integer, string>
....
Countries := CreateAndPopulateCountryDict;
try
// do stuff with Countries
finally
Countries.Free;
end;
你应该在Form Create方法中创建字典,在你需要的地方销毁或清除。不在 LoadCountryList 函数中。
作为 David 回答的扩展,还有另一个使用回调的选项
procedure LoadCountryList( ACallback : TProc<TDictionary<integer,string>> );
var
LCountryList : TDictionary<integer,string>;
begin
// create the instance
LCountryList := TDictionary<integer,string>.Create;
try
// fill the dictionary
// execute the callback
ACallback( LCountryList );
finally
// free the instance
LCountryList.Free;
end;
end;
然后在您的代码中使用它
procedure TCompanyDetailsForm.FormCreate(Sender: TObject);
begin
PageControl1.ActivePage := AddressTab;
LoadCountryList(
procedure ( CountryList : TDictionary<integer,string> )
var
i: Integer;
begin
for i in CountryList.Keys do
begin
LocationCbbx.Items.AddObject(CountryList.Items[i],TObject(i));
end;
end );
end;