Delphi 已发布的持久性属性-我应该使用FMyPersistent.Assign(Value)还是FMyPersistent:=Value?

Delphi 已发布的持久性属性-我应该使用FMyPersistent.Assign(Value)还是FMyPersistent:=Value?,delphi,properties,delphi-xe2,variable-assignment,Delphi,Properties,Delphi Xe2,Variable Assignment,在构建自定义组件时,我可以实现已发布的持久属性。例如 type TMyComponent = class(TComponent) private FMyPersistent: TMyPersistent; ... public ... published property MyPersistent: TMyPersistent read FMyPersistent write SetMyPersistent; ... end;

在构建自定义组件时,我可以实现已发布的持久属性。例如

type
  TMyComponent = class(TComponent)
  private
    FMyPersistent: TMyPersistent;    
    ...
  public
    ...
  published
    property MyPersistent: TMyPersistent read FMyPersistent write SetMyPersistent;
    ...
  end;
请注意,过程
SetMyPersistent
还没有出现,这是下一步的开始。我右键单击此对象并选择“在光标处完成类”(或
Shift+Control+C
)以调用代码完成。当它自动创建此属性设置器时,它会自动将分配代码放入

procedure TMyComponent.SetMyPersistent(const Value: TMyPersistent);
begin
  FMyPersistent := Value;
end;
现在很高兴它继续为我完成了这项任务。然而,在正常情况下,我总是习惯于使用

procedure TMyComponent.SetMyPersistent(const Value: TMyPersistent);
begin
  FMyPersistent.Assign(Value);
end;
如果属性是
String
Integer
等类型,则直接赋值是正确的方法。但是在实现
TPersistent
的已发布属性时,使用
TPersistent.Assign
不是正确的方法吗


使用这两种分配机制的本质区别是什么?因为如果使用
TPersistent.Assign
是适当的操作,那么代码完成有一个轻微的缺陷-即,假设
FMyPersistent:=Value
被认为是“错误的”。

调用
Assign
。这就是为什么您首先有一个属性设置器。如果要直接覆盖该字段,则不需要setter。覆盖它会泄漏您在构造函数中创建的原始对象。在对象检查器中修改属性时,您还会注意到IDE中存在访问冲突


代码完成将相同的代码放入它创建的每个setter中。对于在最终将值存储到字段中之前有额外工作要做的属性,因此field storage语句是正确的。IDE不知道您真正想要什么。

您应该问自己的问题是-谁拥有所涉及的对象?如果您的组件创建并拥有
FMyPersistent
,则使用
FMyPersistent.Assign(Value)
将值从
Value
复制到
FPersistent
。如果
FMyPersistent
仅指向其他人拥有的外部对象,则使用
FMyPersistent:=Value

您是否询问是否应将内容分配给您拥有的对象,而不是将一个对象替换为另一个对象,并泄漏上一个对象?我想你可以自己解决这个问题!如果您的对象在其构造函数中创建FMyPersistent并在其析构函数中释放它,则使用Assign;否则,如果它是弱引用,并且您不拥有或释放该对象,则使用变量FField:=Value。这都是关于所有权的问题。我最初的问题标题是“为什么游标处的完整类对已发布的持久属性进行直接赋值?”但我改变了它,因为它与问题的核心不匹配。这真的很奇怪,为什么那个特定的实例会触发IDE编写一些不正确的代码,而您却不得不替换它。我想知道IDE为什么会做这样的事情,但是这个问题当然会被认为是离题的。@Jerry IDE怎么想并不重要。它没有大脑。你想要推荐信还是复印件?这就是问题所在。你自己决定。IDE无法知道你想要谁拥有一个对象,而不是获取其内容的副本。另一方面,如果它不希望在其位置分配一个新的持久性,那么实际上根本就不应该有一个setter,只是一个只读的持久性属性。欢迎你这么做,但是,该属性在对象检查器中将不可编辑。对象Inspect不显示只读属性,当它指定属性时,它总是像通过赋值语句一样显示只读属性。它不调用
Assign
。因此,如果您希望您的属性以同样的方式可编辑
TFont
TPen
属性是可编辑的,那么您需要提供一个setter,并且需要在其中调用
Assign
(或道德等价物)。不幸的是,这个答案在某些情况下是错误的,例如,当属性是一个TDataset而不是我拥有的对象时。我真的不知道我的答案哪里是错的,@Warren,但不要害羞:请更正它。