我是Delphi的新手,我正在努力更好地理解对象的创建/释放,因为我已经习惯了.NET的奢侈品。我有两个具体问题:
我们假设我正在设置如下的TDataSource。在.NET中,我不会像adoQuery.Free那样明确地销毁对象。但我假设使用Delphi我需要释放这些对象。但是,通过销毁adoQuery,我也将数据集设置为null。通过这种方式,adoQuery只是函数的本地范围变量,只有从函数中重新调用datsource。因此,我怎样才能最好地处理这个问题?
dataSrc := TDataSource.Create(nil);
dataSrc.DataSet := adoQuery;
dataSrc.Enabled := true;
{ adoQuery.Free; }
cnt := DataSrc.DataSet.RecordCount;
从函数返回变量时,我一直在阅读几条建议,最好的办法是在调用者中创建变量并将其传递给子例程。因此,函数的签名看起来像:
AdoConnectionManager.GetResult(query : String; dataSrc: TDataSource) : TDataSource;
Result := dataSrc;
这对我来说没什么吸引力。我更喜欢在子例程中创建一个新变量,然后返回给调用者。但是,这是我从未真正担心的.NET GC,在这里我必须明确销毁变量,对吧?
谢谢!
答案 0 :(得分:2)
你问了两个问题。一个涉及这些数据库类,我将忽略该问题,因为我对这些类一无所知。相反,我会回答其他问题。请注意,这种答案就是为什么网站政策可以一次询问一个问题。
关于返回新对象的函数,这当然是可行的。但是,让调用者提供对象有时更灵活。这允许它们重用实例,或者提供从基类派生的对象。一个典型的例子是填充TStrings
实例的函数。
在这种情况下,您可能使用过程而不是函数。它可能看起来像这样:
procedure PopulateList(List: TMyList);
如果你想要一个函数来返回一个新的实例,那么就像这样做:
function CreateAndPopulateList: TMyList;
begin
Result := TMyList.Create;
try
// code to populate Result goes here, and may raise exceptions
except
Result.Free; // in case of exceptions, we must destroy the instance to avoid leaks
raise;
end;
end;
注意命名。我使用 create 来向调用者暗示创建了一个新实例。调用代码如下所示:
List := CreateAndPopulateList;
try
// do stuff with list
finally
List.Free;
end;
这种模式是标准的对象创建模式。所以你就像使用构造函数一样使用CreateAndPopulateList
。
答案 1 :(得分:1)
这里还应该提到,Delphi还提供了Reference-Counting(但与.NET不同)。
Delphi中对Reference-Counting的简短解释:
与其他语言不同,Delphi中的引用计数仅可通过使用接口来实现。此外,没有Garbage-Collector:当Referencecount达到0时,引用计数的Object会立即被销毁。
因此,作为Delphi开发人员,有以下“全局”规则用于销毁实例:
- 只要声明为ClassType(例如var m:TMyClass),手动销毁对象
- 只要声明为InterfaceType(例如var m:IMyClass),就不会手动销毁对象
答案 2 :(得分:0)
使用Delphi创建对象时,您应该决定如何释放它。有几种方法:
关于第一个问题:你应该明白,用Delphi对象变量是一个指向对象的指针。离开函数时,您可以丢失本地范围(指针)变量,但不会损害对象本身。例如,您可以执行以下操作:
function GetDataSource: TDataSource;
var Query: TADOQuery;
begin
Result := TDataSource.Create(nil);
Query := TADOQuery.Create(Result);
Query.SQL.Text := ' ... ';
Result.DataSet := Query;
end;
它会通过后台查询为您提供所需的数据源。当您释放此数据源时,也将释放查询。
关于第二个问题:返回对象的内部函数创建是一种常规做法,是良好设计的一部分。是的,你应该决定谁将释放这个对象以及如何释放。你可以使用很多策略,这里没有银弹。例如,您可以决定添加参数'数据源的所有者'在上面运作并以这种方式控制它的生命。