You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

匿名方法引发TypeInfo异常行为的技术问询

问题分析

你遇到的这个问题其实是Delphi对匿名方法类型的特殊处理导致的——匿名方法(reference to procedure/function)本质是编译器自动生成的隐式接口类型(继承自IInvokable),但这种类型的TypeInfo并没有像普通类/接口那样被直接暴露出来。当你在泛型函数里直接调用TypeInfo(T)时,编译器无法正确解析这种特殊类型的元数据,就会抛出异常。

解决方案

最可靠的处理方式是借助Delphi的RTTI框架来获取类型信息,它能正确识别编译器生成的匿名方法接口。下面是修改后的泛型函数:

uses
  System.Rtti;

class function GetTypeKind<T>: TTypeKind;
var
  RttiCtx: TRttiContext;
  TargetType: TRttiType;
begin
  RttiCtx := TRttiContext.Create;
  try
    // 用RTTI获取类型信息,自动处理匿名方法类型
    TargetType := RttiCtx.GetType(TypeInfo(T));
    Result := TargetType.TypeKind;

    // 可选:如果你需要明确区分普通接口和匿名方法
    if Result = tkInterface then
    begin
      // 匿名方法接口都继承自IInvokable,通过GUID判断
      if Assigned(TargetType.AsInterface.GetBaseType) and
         (TargetType.AsInterface.GetBaseType.GUID = IInvokable) then
      begin
        // 这里可以添加你的自定义逻辑,比如标记为匿名方法类型
        // 例如:Result := tkAnonymousMethod;(如果你的TTypeKind有这个枚举值)
      end;
    end;
  finally
    RttiCtx.Free;
  end;
end;

替代方案(轻量版)

如果不想引入RTTI依赖,也可以通过异常捕获结合托管类型判断来规避问题,但这种方法准确性稍差(因为托管类型还包括字符串、动态数组等):

class function GetTypeKind<T>: TTypeKind;
var
  TI: PTypeInfo;
begin
  try
    TI := TypeInfo(T);
    Result := TI^.Kind;
  except
    // 捕获TypeInfo获取失败的异常,匿名方法属于托管类型
    if IsManagedType(T) then
      Result := tkInterface
    else
      raise; // 其他异常重新抛出,避免吞掉错误
  end;
end;

为什么原来的代码会失败?

当你定义TMethodProc = reference to procedure;时,编译器会在后台生成一个继承自IInvokable的匿名接口类型,但这个类型的元数据不会被TypeInfo()直接检索到——泛型函数里的TypeInfo(T)尝试访问不存在的元数据,就会触发内存访问异常或类型错误。

内容的提问来源于stack exchange,提问作者Toon Krijthe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:36:17