Delphi 接口未被引用计数
Delphi interface not reference counted
阅读专家 Delphi 书我发现了一些我无法理解的东西。作者用这个代码创建了一个单元:
IToDoData = interface //CRUD
function ToDoCreate(aValue: TToDo): integer;
function ToDoRead(id: integer; out aValue: TToDo): boolean;
function ToDoUpdate(aValue: TToDo): boolean;
function ToDoDelete(id: integer): boolean;
procedure ToDoList(aList: TToDos);
end;
然后他决定用一个DataModule
,实现上面的接口是这样的:
type
TDMToDo = class(TDataModule, IToDoData)
// ... other code ...
public
// IToDoData
function ToDoCreate(aValue: TToDo): integer;
function ToDoRead(id: integer; out aValue: TToDo): boolean;
function ToDoUpdate(aValue: TToDo): boolean;
function ToDoDelete(id: integer): boolean;
procedure ToDoList(aList: TToDos);
end;
到目前为止一切顺利,但请注意,他没有 放置TInterfacedObject
,所以这里我们没有 AddRef 等方法。我的猜测是上面的代码没问题,但它必须包含在 try ... finally 块中。
在主窗体中(数据模块单元当然是uses子句)有这样一个函数:
function TFormToDo.GetToDoData: IToDoData;
begin
if DMToDo = nil then
DMToDo := TDMToDo.Create(Application);
Result := DMToDo;
end;
上面的代码允许这样写:
begin
GetToDoData.ToDoList(FToDos);
ListView1.BeginUpdate;
try
//populate the list
finally
ListView1.EndUpdate;
end;
end;
这不会产生内存泄漏吗?至少 windows。我是 delphi 的新手,所以我可能会失败,但我在网上看到 Android 和 IOs 有 ARC,所以无需担心 try finally。
Windows 没有 ARC 所以我必须使用 try .. finally 除非有像 TInterfacedObject 这样的实现(这里没有)。那么这是一个错误吗?
该应用程序是关于一个 ToDo 应用程序,您可以在其中 write/read/save 您的笔记。数据模块具有 FireDAC 访问组件,接口方法用于访问数据库。这是为了在 UI 和数据库之间保持分离。
TDataModule
是 TComponent
后代,并且 TComponent
实现了 IInterface
和相关的引用计数方法
TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
但是,TComponent
禁用了引用计数,并且在非 ARC 编译器上手动或通过所有权模型管理组件。
更准确地说,TComponent
已禁用引用计数,除非它用作 Windows COM 对象的包装器。这不是这里的情况。
在 ARC 编译器上,手动管理稍微有些复杂 - 实际上是自动管理,因为如果您不允许 TComponent
后代通过所有权进行管理,则必须使用 DisposeOf
释放它们.
TComponent
行为不同于 TInterfacedObject
关于经典编译器引用计数的行为。
在上述情况下,没有泄漏,因为 Application
拥有该数据模块,并且它将在所有编译器上适当地管理数据模块生命周期。
try... finally
块不是用于内存管理,而是用于保护 BeginUpdate... EndUpdate
您必须在所有编译器上保留 try...finally
。
阅读专家 Delphi 书我发现了一些我无法理解的东西。作者用这个代码创建了一个单元:
IToDoData = interface //CRUD
function ToDoCreate(aValue: TToDo): integer;
function ToDoRead(id: integer; out aValue: TToDo): boolean;
function ToDoUpdate(aValue: TToDo): boolean;
function ToDoDelete(id: integer): boolean;
procedure ToDoList(aList: TToDos);
end;
然后他决定用一个DataModule
,实现上面的接口是这样的:
type
TDMToDo = class(TDataModule, IToDoData)
// ... other code ...
public
// IToDoData
function ToDoCreate(aValue: TToDo): integer;
function ToDoRead(id: integer; out aValue: TToDo): boolean;
function ToDoUpdate(aValue: TToDo): boolean;
function ToDoDelete(id: integer): boolean;
procedure ToDoList(aList: TToDos);
end;
到目前为止一切顺利,但请注意,他没有 放置TInterfacedObject
,所以这里我们没有 AddRef 等方法。我的猜测是上面的代码没问题,但它必须包含在 try ... finally 块中。
在主窗体中(数据模块单元当然是uses子句)有这样一个函数:
function TFormToDo.GetToDoData: IToDoData;
begin
if DMToDo = nil then
DMToDo := TDMToDo.Create(Application);
Result := DMToDo;
end;
上面的代码允许这样写:
begin
GetToDoData.ToDoList(FToDos);
ListView1.BeginUpdate;
try
//populate the list
finally
ListView1.EndUpdate;
end;
end;
这不会产生内存泄漏吗?至少 windows。我是 delphi 的新手,所以我可能会失败,但我在网上看到 Android 和 IOs 有 ARC,所以无需担心 try finally。
Windows 没有 ARC 所以我必须使用 try .. finally 除非有像 TInterfacedObject 这样的实现(这里没有)。那么这是一个错误吗?
该应用程序是关于一个 ToDo 应用程序,您可以在其中 write/read/save 您的笔记。数据模块具有 FireDAC 访问组件,接口方法用于访问数据库。这是为了在 UI 和数据库之间保持分离。
TDataModule
是 TComponent
后代,并且 TComponent
实现了 IInterface
和相关的引用计数方法
TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
但是,TComponent
禁用了引用计数,并且在非 ARC 编译器上手动或通过所有权模型管理组件。
更准确地说,TComponent
已禁用引用计数,除非它用作 Windows COM 对象的包装器。这不是这里的情况。
在 ARC 编译器上,手动管理稍微有些复杂 - 实际上是自动管理,因为如果您不允许 TComponent
后代通过所有权进行管理,则必须使用 DisposeOf
释放它们.
TComponent
行为不同于 TInterfacedObject
关于经典编译器引用计数的行为。
在上述情况下,没有泄漏,因为 Application
拥有该数据模块,并且它将在所有编译器上适当地管理数据模块生命周期。
try... finally
块不是用于内存管理,而是用于保护 BeginUpdate... EndUpdate
您必须在所有编译器上保留 try...finally
。