Delphi - 泛型类型约束序数类型

时间:2015-02-04 14:17:07

标签: delphi generics delphi-xe7

我希望为类型Integer和string绑定类型T:

interface

type
  MyFactory<T> = class
  public
    function createGenerator<T:Integer,string>:IGenerator<T>;
  end;

但编译器给出:&#39;(..)E2510 Type&#39; Integer&#39;不是一个有效的约束&#39;。如何将类型T限制为整数或字符串?或者这是一个问题,因为我使用的是序数类型?

1 个答案:

答案 0 :(得分:8)

Delphi泛型不支持序数或字符串类型约束。

只允许约束

  • 零,一个或多个接口类型
  • 零或一个班级类型
  • 保留字&#34;构造函数&#34;,&#34; class&#34;,或&#34;记录&#34;

Delphi Constraints in Generics

我只能猜到你想要完成什么,但是下面的代码可能会给你一些想法

  IGenerator<T> = interface
    function Generate: T;
  end;

  TStringGenerator = class(TInterfacedObject, IGenerator<string>)
  public
    function Generate: string;
  end;

  TIntegerGenerator = class(TInterfacedObject, IGenerator<integer>)
  public
    function Generate: integer;
  end;

  MyFactory<T> = class
  public
    class function createGenerator<T>: IGenerator<T>;
  end;

class function MyFactory<T>.createGenerator<T>: IGenerator<T>;
var
  gs: IGenerator<string>;
  gi: IGenerator<integer>;
begin
  if TypeInfo(T) = TypeInfo(string) then
    begin
      gs := TStringGenerator.Create;
      Result := IGenerator<T>(gs);
    end
  else
  if TypeInfo(T) = TypeInfo(integer) then
    begin
      gi := TIntegerGenerator.Create;
      Result := IGenerator<T>(gi);
    end
  else Result := nil;
end;

function TIntegerGenerator.Generate: integer;
begin
  Result := 10;
end;

function TStringGenerator.Generate: string;
begin
  Result := 'abc';
end;

var
  i: integer;
  s: string;

  i := MyFactory<integer>.createGenerator<integer>.generate;
  s := MyFactory<string>.createGenerator<string>.generate;
也可以使用

TTypeKind代替TypeInfo来确定类型。主要区别在于TypeInfo为您提供了确切使用的类型,而TTypeKind涵盖了属于特定类别的所有类型。虽然TTypeKind提供了更大的灵活性,但如果代码依赖于类型转换,则应谨慎使用。例如,tkInteger涵盖了integerbyte类型,而类型转换可能会导致错误。

class function MyFactory<T>.createGenerator<T>: IGenerator<T>;
var
  gs: IGenerator<string>;
  gi: IGenerator<integer>;
begin
  case PTypeInfo(TypeInfo(T)).Kind of
    tkUString :
      begin
        gs := TStringGenerator.Create;
        Result := IGenerator<T>(gs);
      end;
    tkInteger :
      begin
        gi := TIntegerGenerator.Create;
        Result := IGenerator<T>(gi);
      end
    else Result := nil;
  end;
end;