Delphi 2009泛型编译问题

时间:2008-11-06 23:13:10

标签: delphi generics delphi-2009

我正在检查Delphi 2009试用版,但是立即遇到了仿制药问题。

下面的代码没有编译,我一点也不知道为什么它给了我E2015的Equals()方法:

type
  TPrimaryKey<T> = class(TObject)
  strict private
    fValue: T;
  public
    constructor Create(AValue: T);
    function Equals(Obj: TObject): boolean; override;
    function GetValue: T;
  end;

constructor TPrimaryKey<T>.Create(AValue: T);
begin
  inherited Create;
  fValue := AValue;
end;

function TPrimaryKey<T>.Equals(Obj: TObject): boolean;
begin
  Result := (Obj <> nil) and (Obj is TPrimaryKey<T>)
    and (TPrimaryKey<T>(Obj).GetValue = fValue);
end;

function TPrimaryKey<T>.GetValue: T;
begin
  Result := fValue;
end;

为什么编译器认为无法比较fValue和GetValue()的结果?

4 个答案:

答案 0 :(得分:6)

如果T是一个字符串怎么办?如果它是TSize记录怎么办?

不限制T(例如,使用&lt; T:class&gt;),您无法确定比较是否有意义。

相反,如果要比较T类型的两个值,可以使用Generics.Defaults单元并使用:

TEqualityComparer<T>.Default.Equals(x, y)

比较T类型的值x和y。

答案 1 :(得分:3)

您不能将运算符与无类型泛型一起使用。有关讨论,请参阅here

如果您将其更改为:

,则会编译
TPrimaryKey<T: class> = class(TObject)

答案 2 :(得分:2)

我认为原始海报试图围绕简单类型(整数,双等等)创建一个对象包装器,因此将T限制为类可能不适用于他想要的东西。

答案 3 :(得分:1)

编译器无法确定两个“T”是否相同。但是通过一个小技巧,你可以使它工作:

type
  TPrimaryKey<T> = class(TObject)
  public
    type
      TCompare<T1> = reference to function(const A1, A2: TPrimaryKey<T1>): Boolean;
  private
    fValue: T;
    fCompare : TCompare<T>;
  public
    constructor Create(AValue: T; ACompare: TCompare<T>);
    function Equals(Obj: TPrimaryKey<T>): Boolean; reintroduce;
    function GetValue: T;
    function CreateNew(const AValue: T): TPrimaryKey<T>;

  end;

constructor TPrimaryKey<T>.Create(AValue: T; ACompare: TCompare<T>);
begin
  inherited Create;
  fValue := AValue;
  fCompare := ACompare;
end;

function TPrimaryKey<T>.Equals(Obj: TPrimaryKey<T>): Boolean;
begin
  Result := FCompare(self, Obj);
end;

function TPrimaryKey<T>.GetValue: T;
begin
  Result := fValue;
end;

function TPrimaryKey<T>.CreateNew(const AValue: T): TPrimaryKey<T>;
begin
  Result := TPrimaryKey<T>.Create(AValue, FCompare);
end;

使用以下方法对其进行实例化:

var
  p1, p2 : TPrimaryKey<Integer>;
begin
  p1 := TPrimaryKey<Integer>.Create(10,
    function(const A1, A2: TPrimaryKey<Integer>): Boolean
    begin
      Result := (A1<>nil) and (A2<>nil) and (A1.GetValue=A2.GetValue);
    end);
  p2 := p1.CreateNew(10);

  p1.Equals(p2);
end;