- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这里是一些示例代码,它是 Delphi 中的一个独立控制台应用程序,它创建一个对象,然后创建一个 TInterfacedObject
对象,并将 Interface 引用分配给 TObject 中的字段:
program ReferenceCountingProblemProject;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
ITestInterface = interface
['{A665E2EB-183C-4426-82D4-C81531DBA89B}']
procedure AnAction;
end;
TTestInterfaceImpl = class(TInterfacedObject,ITestInterface)
constructor Create;
destructor Destroy; override;
// implement ITestInterface:
procedure AnAction;
end;
TOwnerObjectTest = class
public
FieldReferencingAnInterfaceType1:ITestInterface;
end;
constructor TTestInterfaceImpl.Create;
begin
WriteLn('TTestInterfaceImpl object created');
end;
destructor TTestInterfaceImpl.Destroy;
begin
WriteLn('TTestInterfaceImpl object destroyed');
end;
procedure TTestInterfaceImpl.AnAction;
begin
WriteLn('TTestInterfaceImpl AnAction');
end;
procedure Test;
var
OwnerObjectTest:TOwnerObjectTest;
begin
OwnerObjectTest := TOwnerObjectTest.Create;
OwnerObjectTest.FieldReferencingAnInterfaceType1 := TTestInterfaceImpl.Create as ITestInterface;
OwnerObjectTest.FieldReferencingAnInterfaceType1.AnAction;
OwnerObjectTest.Free; // This DOES cause the clearing of the interface fields automatically.
ReadLn; // wait for enter.
end;
begin
Test;
end.
我编写这段代码是因为我不确定在一些简单的例子中,Delphi 是否总是会清除我的接口(interface)指针。这是程序运行时的输出:
TTestInterfaceImpl object created
TTestInterfaceImpl AnAction
TTestInterfaceImpl object destroyed
这是我非常希望看到的输出。我编写这个程序的原因是因为我发现我正在开发的大型 Delphi 应用程序中违反了“我和 Delphi 之间的契约(Contract)”。我看到对象没有被释放,除非我在析构函数中明确地将它们归零,如下所示:
destructor TMyClass.Destroy;
begin
FMyInterfacedField := nil; // work around leak.
end;
我相信 Delphi 正在尽最大努力将这些接口(interface)归零,因此,当我在上面的测试代码中的析构函数上设置断点时,我得到以下调用堆栈:
ReferenceCountingProblemProject.TTestInterfaceImpl.Destroy
:00408e5f TInterfacedObject._Release + $1F
:00408d77 @IntfClear + $13
ReferenceCountingProblemProject.ReferenceCountingProblemProject
正如您所看到的,正在生成对 @IntfClear
的调用,但上面的调用堆栈中缺少“Free”,这让我有点困惑,因为这两者似乎存在因果关系,但是不直接在彼此的调用路径中。这表明编译器本身在调用析构函数 TObject.Free
之后的某个时刻在我的应用程序中发出 @IntfClear
。我正确地阅读了这个标志吗?
我的问题是:Delphi 的 TObject 是否始终保证接口(interface)类型字段的最终确定?如果没有,什么时候我的接口(interface)会被清除,什么时候我必须手动清除它?接口(interface)引用的最终确定是作为 TObject 的一部分实现的,还是作为某些通用编译器范围语义的一部分实现的?事实上,关于何时手动将接口(interface)清零以及何时让 Delphi 为我做这件事,我应该遵循哪些规则?想象一下,我的应用程序中有(正如我确实有的)200 多个将接口(interface)存储为字段的类。我是否在析构函数中将它们全部设置为 Nil?我如何决定要做什么?
我的怀疑是,(a)TObject 提供了这种保证,但条件是,如果你做了一些愚蠢的事情,并且不知何故没有在包含接口(interface)引用字段的对象上调用 TObject.Destroy,那么你就会泄漏两者,或者(b)低于 TObject 级别的编译器在超出范围的级别上提供了这种语义保证,而正是这一面让我摸不着头脑,无法解释我的复杂场景现实世界中可能会遇到。
对于一些微不足道的情况,比如我从上面的演示中删除 OwnerObjectTest.Free;
的情况,并且您泄漏了演示代码创建的两个对象,我可以毫无问题地理解该语言的行为/compiler/runtime,但我希望确保我已完全理解与接口(interface)类型的对象中的字段相关的契约(Contract)或保证(如果有)。
更新通过单步执行并声明我自己的析构函数,我能够获得不同的调用堆栈,这更有意义:
ReferenceCountingProblemProject.TTestInterfaceImpl.Destroy
:00408e5f TInterfacedObject._Release + $1F
:00408d77 @IntfClear + $13
:00405483 TObject.Free + $B
ReferenceCountingProblemProject.ReferenceCountingProblemProject
这似乎表明 @IntfClear
是由 TObject.Free
调用的,这是我非常期望看到的。
最佳答案
当执行对象的析构函数时,对象实例的所有字段都将被最终确定。这是由运行时保证的。事实上,托管类型的所有字段都在销毁时完成。
此类引用计数对象未被销毁的可能解释是:
关于delphi - TObject 对于在对象销毁时清除接口(interface)字段提供什么保证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20860548/
编写一个仅用于集中其他接口(interface)的接口(interface)是好的做法还是坏的做法? interface InterfaceA : InterfaceB, InterfaceC { }
有没有一种方法可以确定具体类型从任意接口(interface)列表?我知道类型转换,但我想知道所有满意的接口(interface)。 例如,给定: type Mover interface { Mo
我正在尝试制作斐波那契堆。 (在我正在上的算法课中多次提到它们,我想检查一下。)我希望堆使用任何类型的节点,所以我定义了一个 Node 接口(interface): package node type
这是我的代码: type IA interface { FB() IB } type IB interface { Bar() string } type A struct {
示例 A: // pseudo code interface IFoo { void bar(); } class FooPlatformA : IFoo { void bar() {
合并它编译的 leppies 反馈 - 但 IMO 有一些缺点,我希望编译器强制每个子类定义它们自己的 Uri 属性。现在的代码: [] type UriUserControl() = inh
我正在构建一个项目,该项目从用户那里获取一个术语,然后执行谷歌搜索并返回一个 json 格式的标题列表。 我正在使用 serpwow API 来执行谷歌搜索并试图解析响应。 但是我收到的错误是: pa
我只想在其他接口(interface)中实现某些接口(interface),我不希望它们能够被类直接继承。 提前致谢! 最佳答案 您不能在 C# 中执行此操作 - 任何类都可以实现它有权访问的任何接口
我是 Go 的新手,还有一些我还没有掌握的技巧 例如,我有一个可以这样调用的函数: myVar.InitOperation("foo",Operator.EQUAL,"bar") myVar.Init
我有一个通用接口(interface)来描述对输出流的访问,如下所示: interface IOutput { function writeInteger(aValue:Int):Void;
我正在做一个项目,我想通过某种接口(interface)(最好是 USB)将光电探测器电路安装到计算机上。但是,由于我是新手,所以我不知道应该朝哪个方向处理这个问题。假设我有一个带有 USB 连接的光
背景 我正在尝试创建一个简单的应用程序,以真正理解DDD + TDD + etc的整个堆栈。我的目标是在运行时动态注入DAL存储库类。这让我 域和应用程序服务层可测试。我打算用“穷人的DI”来完成 现
在 Java 中,接口(interface)扩展接口(interface)是完全合法的。 UML 中的这种关系看起来像“扩展”关系(实线、闭合、未填充的箭头)还是“实现”关系(虚线、闭合、未填充的箭头
我想创建一个具有相等和比较函数默认实现的接口(interface)。 如果我从类型 IKeyable 中删除所有内容除了Key成员,只要我不添加默认实现,它就是一个有效的接口(interface)。从
COM 中的双接口(interface)是能够通过 DispInterface 或 VTable 方法访问的接口(interface)。 现在有人可以告诉我这两种方法之间到底有什么区别吗? 我认为 V
我有一个类方法,它返回一个可以迭代的员工列表。返回列表的最佳方式是什么?通常我只返回一个 ArrayList。然而,据我了解,界面更适合这种类型的操作。哪个是最好使用的界面?另外,为什么返回接口(in
我想从包装类外部实例化一个内部非静态接口(interface)。 这可能吗? 考虑以下代码: shared class AOuterClass() { Integer val = 3; shared
我为一个类编写了一个接口(interface),如下所示: public interface IGenericMultipleRepository { Lazy> addresses { ge
我是 UML 的初学者,现在我正在创建一个序列图,问题是我想根据用户输入实现 DAO 接口(interface)。如何在时序图中正确绘制以实现接口(interface)。 最佳答案 您不会在 SD 上
要使用 jsr 303 验证创建有条件验证的组,请将接口(interface)类传递给注释,如下所示: @NotEmpty (groups={UpdateValue.class}) 我有很多不同的接口
我是一名优秀的程序员,十分优秀!