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

dav*_*l12 2 delphi generics delphi-xe7

我想为两种类型的Integer和string绑定类型T:

interface

type
  MyFactory<T> = class
  public
    function createGenerator<T:Integer,string>:IGenerator<T>;
  end;
Run Code Online (Sandbox Code Playgroud)

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

Dal*_*kar 9

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

只允许约束

  • 零,一个或多个接口类型
  • 零或一类类型
  • 保留字"构造函数","类"或"记录"

Delphi在泛型中的约束

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

  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;
Run Code Online (Sandbox Code Playgroud)

也可以使用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;
Run Code Online (Sandbox Code Playgroud)