测试接口是否等于类型参数

时间:2017-04-28 12:01:08

标签: delphi generics interface

我有一个可以保存接口的列表 我想要一个删除功能,只删除支持特定接口的项目。

type
  TMyList<T: IFoo> = class
    procedure Remove(const Item: T); overload; 
    procedure Remove<I: IBar>(const Item: T); overload;
  end;

procedure TMyList<T>.Remove<I>(const Item: T);
begin
  if Supports(Item, I) then Remove(Item);
end;
  

E2250没有超载版本的支持&#39;可以用这些参数调用

有没有办法可以做到这一点?

2 个答案:

答案 0 :(得分:4)

是的,虽然您不能这样传递接口类型参数,但您可以传递TGUID并将接口类型分配给TGUID,前提是您在接口声明中声明了GUID以开始用。

实施例

type
  IFoo = interface
    ['{93863A49-5014-4AE5-A7CF-F3F2E044CE57}']  //<Ctrl>+<Shift>+G
   ....
  end;

  IBar = interface(IFoo)
    ['{88888888-5014-4AE5-A7CF-F3F2E044CE57}']
    ....
  end;

  procedure TFooList.Remove(const Item: IFoo; const MustBeA: TGuid); {overload;}
  begin
    if Supports(Item, MustBeA) then Remove(Item);

  ....
  for i:= 0 to count-1 do begin
    //Only remove IBar16 items
    MyFooList.Remove(FooList[i], IBar16);
  end;

答案 1 :(得分:3)

首先,两个接口应该有一个用它们声明的GUID(如果你还没有这样做)。

type
   IBar = interface
   ['{08C764E8-3EF4-42A7-94B7-8D1C5371DF25}']
   end;

   IFoo = interface
   ['{30B9440D-A012-4C7D-8422-A80D7E18F4E5}']
   end;

然后,您应该能够将呼叫更改为&#34;支持&#34;对此:

uses System.TypInfo;

function TMyList<T>.Remove<I>(const Item: T);

begin
   //if Supports(Item, I) then Remove(Item);
   if Supports(Item, GetTypeData( TypeInfo(I) )^.GUID) then Remove(Item);

  //  ...
end;

虽然编译器没有&#34;知道&#34;那&#34;我&#34;是一种接口类型,你做 - 因为你限制它。因此,可以安全地从TypeData中提取GUID,用于&#34; I&#34;。

通用类型约束(类,接口或记录)声明或细化引用或使用的代码中泛型参数的数据类型。相反,它们只是允许编译器限制泛型类型的使用方式。

type
   IBar = interface
   ['{08C764E8-3EF4-42A7-94B7-8D1C5371DF25}']
   end;

   IFoo = interface
   ['{30B9440D-A012-4C7D-8422-A80D7E18F4E5}']
   end;

   IFoo1 = interface(IFoo)
   ['{6C3D06C9-C0B7-45CD-80F2-45123ECC5E9C}']
   end;
   IFoo2 = interface(IFoo)
   ['{9C3AB5F7-E88C-4620-AFC5-B83340048531}']
   end;


   TMyList<T: IFoo> = class
   end;

&lt; T:IFoo&gt;约束将允许这些:

 var
     L : TMyList<IFoo>;
     L : TMyList<IFoo1>;
     L : TMyList<IFoo2>;

但不是这样:

     L : TMyList<IBar>;

而且,最重要的是,在3次有效的扩展中,&#34; T&#34; 成为接口类型。它仍然是通用的或&#34;类型未知&#34;在编译器的眼中。

&#34;构造函数&#34;约束是此规则的一个例外。它将要求泛型参数为类类型,但更重要的是,它允许通过无参数构造函数实例化目标类,而不使用类型转换。

type
   TMyClass = class
      constructor Create;
      procedure   DoSomething;
   end;

constructor TMyClass.Create;
begin
end;

procedure TMyClass.DoSomething;
begin
end;

type
   TMyGeneric2<T:constructor> = class
      procedure Perform;
   end;

procedure TMyGeneric2<T>.Perform;

var
   x : T;

begin
   x := T.Create;   // This is allowed...
   x.DoSomething;   // ...but this is not.
end;

当您使用泛型类型参数约束时,您没有解析泛型参数的类型。您只需设置一些规则,以便编译器在使用该泛型类型时遵循。