【问题标题】:E2010 Incompatible types: 'System.Rtti.T' and 'MyInterfaceImpl.T' genericE2010 不兼容的类型:“System.Rtti.T”和“MyInterfaceImpl.T”泛型
【发布时间】:2021-08-31 08:02:12
【问题描述】:

我使用 Delphi 10.3。我有两种方法实现,用于将枚举类型转换回和 fort 为字符串。这不是真正的实现,只是服务本质的两个变体:

案例一:

TMyClass = class
  private
    ctx : TRTTIContext;
  public
    function asString<T>( const value_ : T ) : string;
    function fromString<T>( const value_ : string ) : T;
end;

function TMyClass.asString<T>( const value_ : T ) : string;
var
  rttiType : TRTTIType;
begin
  rttiType := ctx.getType( typeInfo( T ) );
  if ( rttiType.typeKind = tkEnumeration ) then
  begin
    result := TRTTIEnumerationType( rttiType ).getName( value_ );
  end;
end;

function TMyClass.fromString<T>( const value_ : string ) : T;
var
  rttiType : TRTTIType;
begin
  rttiType := ctx.getType( typeInfo( T ) );
  if ( rttiType.typeKind = tkEnumeration ) then
  begin
    result := TRTTIEnumerationType( rttiType ).getValue( value_ );
  end;
end;

案例2:

IMyInterface<T> = interface
  ['{C03754B7-2225-4EB5-97C1-9820B3D1EBAD}']
  function asString( const value_ : T ) : string;
  function fromString( const value_ : string ) : T;
end;

TMyInterfaceImpl<T> = class ( TInterfacedObject, IMyInterface<T> )
  private
    ctx : TRTTIContext;
  public
    function asString( const value_ : T ) : string;
    function fromString( const value_ : string ) : T;
end;

function TMyInterfaceImpl<T>.asString( const value_ : T ) : string;
var
  rttiType : TRTTIType;
begin
  rttiType := ctx.getType( typeInfo( T ) );
  if ( rttiType.typeKind = tkEnumeration ) then
  begin
    result := TRTTIEnumerationType( rttiType ).getName( value_ );
  end;
end;

function TMyInterfaceImpl<T>.fromString( const value_ : string ) : T;
var
  rttiType : TRTTIType;
begin
  rttiType := ctx.getType( typeInfo( T ) );
  if ( rttiType.typeKind = tkEnumeration ) then
  begin
    result := TRTTIEnumerationType( rttiType ).getValue( value_ );
  end;
end;

TRTTIEnumeration.GetName/GetValueTMyClass 实现中工作正常,但在TMyInterfaceImpl&lt;T&gt; 中无法编译:

E2010 Incompatible types: 'System.Rtti.T' and 'MyInterfaceImpl.T'

E2531 Method 'GetValue' requires explicit type argument(s)

但我想将此服务实现为接口。 TMyInterfaceImpl&lt;T&gt; 有什么解决方案吗?接口中不允许使用泛型类型参数化方法。 (procedure foo&lt;T&gt;( const value_ : T );)

【问题讨论】:

  • 您的 IMyInterface 声明是什么?您的 TMyClass 无法编译并出现相同的错误。您需要在通话中使用 getValue 和 getName
  • @DalijaPrasnikar IMyInterface 就像在实现中一样声明asStringfromString。我把它放到代码示例中。你说的对!我刚刚成功测试了TMyClass.asStringgetName,并且我假设'TMyClass.fromString 也可以编译。但它会导致与接口实现中相同的错误消息。它变得越来越陌生。一种 TRTTIEnumerationType 方法调用有效,另一种无效。
  • @DalijaPrasnikar 将您的 getValue 和 getName 评论转换为答案,我会接受。令人惊讶的是,我应该打电话给TRTTIEnumerationTypee.getName&lt;T&gt;( value_ ) 而不是TRTTIEnumerationTypee.getName( value_ );。感谢您的回答。

标签: delphi generics


【解决方案1】:

TRTTIEnumerationType 中的GetNameGetValue 类函数是参数化函数:

class function GetName<T{: enum}>(AValue: T): string; reintroduce; static;
class function GetValue<T{: enum}>(const AName: string): T; static;

您需要在调用GetName&lt;T&gt;(...)GetValue&lt;T&gt;(...)时添加T

function TMyInterfaceImpl<T>.asString( const value_ : T ) : string;
var
  rttiType : TRTTIType;
begin
  rttiType := ctx.getType( typeInfo( T ) );
  if ( rttiType.typeKind = tkEnumeration ) then
  begin
    result := TRTTIEnumerationType( rttiType ).getName<T>( value_ );
  end;
end;

function TMyInterfaceImpl<T>.fromString( const value_ : string ) : T;
var
  rttiType : TRTTIType;
begin
  rttiType := ctx.getType( typeInfo( T ) );
  if ( rttiType.typeKind = tkEnumeration ) then
  begin
    result := TRTTIEnumerationType( rttiType ).getValue<T>( value_ );
  end;
end;

【讨论】:

  • 感谢您的解决方案。我对方法调用很粗心。重新考虑一下,定义 Enum 类型似乎是合乎逻辑的。 TRTTIEnumerationType 没有自己定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 2015-08-11
  • 2012-04-26
相关资源
最近更新 更多