9

我制作了一个自定义 TObjectList 后代,旨在保存基对象类的子类。它看起来像这样:

interface
   TMyDataList<T: TBaseDatafile> = class(TObjectList<TBaseDatafile>)
   public
      constructor Create;
      procedure upload(db: TDataSet);
   end;

implementation

constructor TMyDataList<T>.Create;
begin
   inherited Create(true);
   self.Add(T.Create);
end;

我希望每个新列表都以其中的一个空白对象开始。这很简单,对吧?但是编译器不喜欢它。它说:

“无法在类型参数声明中创建没有 CONSTRUCTOR 约束的新实例”我只能假设这是与泛型相关的东西。任何人都知道发生了什么以及如何使这个构造函数工作?

4

2 回答 2

17

您正在尝试创建Tvia的实例T.Create。这不起作用,因为编译器不知道您的泛型类型具有无参数构造函数(请记住:这不是必需的)。为了纠正这个问题,您必须创建一个构造函数约束,如下所示:

<T: constructor>

或者,在您的具体情况下:

<T: TBaseDatafile, constructor>
于 2008-12-20T20:23:31.897 回答
2

只是对一个老问题的快速更新..

您不需要构造函数约束,也可以通过像这样使用 RTTI(使用带有 XE2 的 RTTI 或 System.RTTI)对带有参数的对象执行此操作

constructor TMyDataList<T>.Create;
var
  ctx: TRttiContext;
begin
   inherited Create(true);
   self.Add(
     ctx.
     GetType(TClass(T)).
     GetMethod('create').
     Invoke(TClass(T),[]).AsType<T>
   );
end;

如果您有参数,只需像这样添加它们

constructor TMyDataList<T>.Create;
var
  ctx: TRttiContext;
begin
   inherited Create(true);
   self.Add(
     ctx.
     GetType(TClass(T)).
     GetMethod('create').
     Invoke(TClass(T),[TValue.From('Test'),TValue.From(42)]).AsType<T>
   );
end;
于 2011-09-04T20:04:55.423 回答