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

Delphi - Generics type constraint ordinal types

我想为整数和字符串类型绑定类型 T:

interface

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

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

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

唯一允许的约束是

  • 零种、一种或多种接口类型
  • 零个或一个 class 类型
  • 保留字"constructor"、"class"或"record"

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;