2

我正在查看 Delphi 2009 Trial,但马上就遇到了泛型问题。

以下代码无法编译,我一点也不知道为什么它给我 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

4 回答 4

6

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

如果没有约束 T(例如使用 <T :class>),您无法确定比较是否有意义。

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

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

比较类型 T 的值 x 和 y。

于 2008-11-06T23:57:37.340 回答
3

您不能将运算符与无类型的泛型一起使用。请参阅此处进行讨论。

如果您将其更改为:

TPrimaryKey<T: class> = class(TObject)
于 2008-11-06T23:37:58.020 回答
2

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

于 2008-11-06T23:46:51.747 回答
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;
于 2008-11-06T23:48:39.463 回答