String 在TObject类型的属性中存储字符串最轻量级的方法是什么?
情况: 我从String 在TObject类型的属性中存储字符串最轻量级的方法是什么?,string,delphi,delphi-xe2,boxing,String,Delphi,Delphi Xe2,Boxing,情况: 我从TDataSet创建可视组件,该组件应保留一个id作为参考。组件只能存储对象,不能存储字符串 伪代码: for Record in DataSet do AddComponent.Data := Record['id'] 其中,Data是类型TObject,而id字段是字符串类型(实际上是GUID) 问题是: 如何在对象属性中存储字符串 我尝试了一种使用自定义类型TBox的装箱解决方案,但我希望避免内存管理问题 如何在对象属性中存储字符串 为什么? 那么 sizeof(TObj
TDataSet
创建可视组件,该组件应保留一个id作为参考。组件只能存储对象,不能存储字符串
伪代码:
for Record in DataSet do
AddComponent.Data := Record['id']
其中,Data
是类型TObject
,而id
字段是字符串类型(实际上是GUID)
问题是:
如何在对象属性中存储字符串
我尝试了一种使用自定义类型TBox
的装箱解决方案,但我希望避免内存管理问题
如何在对象属性中存储字符串
为什么?
那么
sizeof(TObject)=sizeof(指针)
String
是ref-counted类型,因此您可以使用StringRec
cracker类型并管理所有的内部函数,或者使用compielr内置计数器。我会尝试第二种方法,尽管它效率较低,并且增加了额外的间接级别Dispose(…)
procedure TMyComponent.BeforeDestruction;
var P: PStringContainer;
begin
P := Pointer(Data);
Data := nil;
Dispose(P); // should free the string, since P type was given
inherited;
end;
我想避免内存管理问题
具体是哪类问题以及程序的哪一部分?如果
数据的类型是TObject
,则无法避免内存管理问题。编译器不会为您管理TObject
实例的生存期。您必须使用标准的生命周期管理机制之一:
您可以使用try/finally块和显式调用Free
来处理它
您可以从TComponent
派生对象,并将其归某个对象所有,该对象保证比对包装字符串的所有引用都有效
选项2有许多变体。移交所有权的其他方法包括使用接口。只要所有者在对象的所有引用之后仍然存在,那么您就是安全的
就我个人而言,我不太喜欢选项2。如果编译器不打算管理对象的生命周期,我宁愿自己管理它。我发现如果我使用显式管理,那么就更容易推断对象的生命何时结束。我是否可以建议通过StringToGUID
将Record
中包含的GUID存储到中,将TGUID
作为适当的对象。它将同时为GUID提供一个健全的检查,这可能是一件好事。我希望Delphi有对象的引用计数。@J。。。数据库已经确保字符串是有效的GUID。@JensMühlenhoff下一代编译器将支持对象的自动引用计数。@DavidHeffernan太好了,我期待下一代编译器:)这听起来不像TBox
那么复杂。这大概是TBox=class FValue:T;结束代码>由内存管理问题我的意思是双重释放或泄漏,字符串由编译器管理,但对象不是。我认为有一些技巧,但我想David是对的。@David依赖于对“复杂”和“轻量级”的解释New/Dispose
当然比对象创建/销毁的深层嵌套调用更轻量级。@Arioch'TheTObject.NewInstance
没有New
那么重。另外,我在这里看到了DataSet
,所以让我们看看更大的图景。NewInstance实际上只是调用序列中的一个。虽然总的来说你对大局的看法是正确的。。。
procedure TMyComponent.BeforeDestruction;
var P: PStringContainer;
begin
P := Pointer(Data);
Data := nil;
Dispose(P); // should free the string, since P type was given
inherited;
end;