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'The
    TObject.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;