Delphi:从什么时候开始,接口引用不再在with块的末尾发布?
我最近遇到了一个由我编写的一些非常旧的代码引起的问题,该问题显然是假设Delphi:从什么时候开始,接口引用不再在with块的末尾发布?,delphi,interface,delphi-2009,reference-counting,with-statement,Delphi,Interface,Delphi 2009,Reference Counting,With Statement,我最近遇到了一个由我编写的一些非常旧的代码引起的问题,该问题显然是假设with语句中使用的接口引用将在with-块离开后立即释放-有点像隐式try finally-块(类似于C#的使用-语句,如果我理解正确的话) 显然(在Delphi 2009中)情况并非如此(不再如此)。有人知道这是什么时候发生的吗?或者我的代码一开始就完全错了 为了澄清,这里有一个简化的示例: type IMyIntf = interface; TSomeObject = class(TInterfacedObjec
with
语句中使用的接口引用将在with
-块离开后立即释放-有点像隐式try finally
-块(类似于C#的使用
-语句,如果我理解正确的话)
显然(在Delphi 2009中)情况并非如此(不再如此)。有人知道这是什么时候发生的吗?或者我的代码一开始就完全错了
为了澄清,这里有一个简化的示例:
type
IMyIntf = interface;
TSomeObject = class(TInterfacedObject, IMyIntf)
protected
constructor Create; override; // creates some sort of context
destructor Destroy; override; // cleans up the context created in Create
public
class function GetMyIntf: IMyIntf; //a factory method, calling the constructor
end;
procedure TestIt;
begin
DoSomething;
with (TSomeObject.GetMyIntf) do
begin
DoStuff;
DoMoreStuff;
end; // <- expected: TSomeObject gets destroyed because its ref.count is decreased to 0
DoSomethingElse;
end; // <- this is where TSomeObject.Destroy actually gets called
类型
IMyIntf=接口;
TSomeObject=class(TInterfacedObject,IMyIntf)
受保护的
构造函数Create;override;//创建某种上下文
析构函数Destroy;override;//清除在Create中创建的上下文
公众的
类函数GetMyIntf:IMyIntf;//一个工厂方法,调用构造函数
结束;
程序测试;
开始
剂量测定法;
使用(TSomeObject.GetMyIntf)do
开始
多斯塔夫;
多莫瑞斯图夫;
end;//Pascal/Delphi中带有
保留字的仅用于轻松访问记录或对象/类的成员(即,为了不提及记录/对象/类的名称)。它与垃圾收集相关的C#with
非常不同。自记录
诞生之日起,它就存在于Pascal语言中,以简化对许多数据成员的代码调用(当时仅称为“字段”)
总而言之,with
与垃圾收集、内存释放或对象实例的销毁无关。在with
头上构造的对象以前可能只是在单独的代码行中初始化过,这是一样的。此with行为从未改变。若要达到预期的行为您可以通过以下方式更改代码:
procedure TestIt;
var
myIntf: IMyIntf;
begin
DoSomething;
myIntf := TSomeObject.GetMyIntf
DoStuff;
DoMoreStuff;
myIntf := nil; // <- here is where TSomeObject.Destroy called
DoSomethingElse;
end;
程序测试;
变量
myIntf:IMyIntf;
开始
剂量测定法;
myIntf:=TSomeObject.GetMyIntf
多斯塔夫;
多莫瑞斯图夫;
myIntf:=nil;//正确,创建的对象的范围是它的所有者,即本例中的过程。在上面的示例中,它应该在最后一刻被销毁。任何其他操作都是意外的,可能是D2009中更正的错误。自从在版本3中将接口引入Delphi以来,行为一直是相同的。没有修正错误。奥利弗只是忘记了事情是如何运作的。又一个“with”的例子导致意外的结果。我总是想象with
创建一个匿名的、范围严格的局部变量,该变量只存在于with
-块中。对于我来说,即使您无法再访问该引用,内存管理器仍然保留该引用似乎是毫无意义的……考虑到这一点(现在看来:非常不正确)从世界的角度来看,我认为当引用超出范围时,期望引用计数立即减少是完全正确的……并且澄清:我从未期望带有
-block的会直接影响引用对象的生存期-我只期望隐含局部变量的范围限于该块,并且因此,它的引用计数将在该块结束时立即减少。不幸的是,这两个备选方案都违背了保持代码简洁的主要意图之一……而且,在第一个示例中,为了清晰起见,我将添加一个try finally
块(虽然不是严格必要的),我也不喜欢将变量声明为“空”仅为滥用^D^D^D^D^D^D而存在的接口类型利用了接口对象的引用计数特性…我希望尽可能保持这些匿名性…但不可否认,这只是我的个人特质
procedure TestIt;
procedure DoAllStuff;
var
myIntf: IMyIntf;
begin
myIntf := TSomeObject.GetMyIntf
DoStuff;
DoMoreStuff;
end; // <- here is where TSomeObject.Destroy called
begin
DoSomething;
DoAllStuff;
DoSomethingElse;
end;