“ as”和“ is”不适用于通用类型

时间:2019-07-18 13:46:37

标签: generics delphi-10-seattle

令我惊讶的是,泛型不受“ is”和“ as”运算的约束。

如何实现以下目标?

function TDisplayConfManager._getDisplay<T>(parentCtl: TWinControl; indicatorName: string): T;
var
  i: Integer;
  ind: T;
begin
  for i := 0 to parentCtl.ControlCount-1 do
    if parentCtl.Controls[i] is T then begin // E2015 Operator not applicable to this operand type
      ind := parentCtl.Controls[i] as T; // E2015 Operator not applicable to this operand type
      if SameText(ind.Caption, indicatorName) then Exit(ind); // E2003 Undeclared identifier: 'Caption'
    end;
  Result := T.Create(_owner); // E2003 Undeclared identifier: 'Create'
end;

如果我对所有显示器都使用基本显示类,则会出现两个错误,但是我仍然无法使用“ is”来创建对象:

function TDisplayConfManager._getDisplay<T>(parentCtl: TWinControl; indicatorName: string): T;
var
  i: Integer;
  ind: TBaseDisplayType;
begin
  for i := 0 to parentCtl.ControlCount-1 do
    if parentCtl.Controls[i] is T then begin // E2015 Operator not applicable to this operand type
      ind := parentCtl.Controls[i] as TBaseDisplayType;
      if SameText(ind.Caption, indicatorName) then Exit(ind);
    end;
  Result := T.Create(_owner); // E2003 Undeclared identifier: 'Create'
end;

1 个答案:

答案 0 :(得分:1)

原因是T不必是类类型;它也可以是非类类型,例如整数,字符串,记录或数组。

因此以下内容无法编译:

type
  TTest<T> = record
    function Test(AObject: TObject): Boolean;
  end;

{ TTest<T> }

function TTest<T>.Test(AObject: TObject): Boolean;
begin
  Result := AObject is T; // E2015 Operator not applicable to this operand type
end;

但是,如果您知道自己的T类型始终是类类型,则可以在Delphi中表示出来:

type
  TTest<T: class> = record
    function Test(AObject: TObject): Boolean;
  end;

{ TTest<T> }

function TTest<T>.Test(AObject: TObject): Boolean;
begin
  Result := AObject is T;
end;

documentation包含有关通用约束的更多详细信息。

根据评论进行更新:

您还可以在成员级别上设置约束:

type
  TTest = record
    function Test<T: class>(AObject: TObject): Boolean;
  end;

{ TTest }

function TTest.Test<T>(AObject: TObject): Boolean;
begin
  Result := AObject is T;
end;