Too*_*the 6 delphi anonymous-methods typeinfo delphi-10.2-tokyo
对于需要泛型类型"family"的一段代码,我尝试使用它TypeInfo来检索所需的信息.
class function GetTypeKind<T>:TTypeKind;
Run Code Online (Sandbox Code Playgroud)
对于大多数类型,我可以解决这个问题.但匿名方法类型表现出意外.
我有一个匿名方法类型定义为:
TMethodProc = reference to procedure;
Run Code Online (Sandbox Code Playgroud)
我试着获取类型信息:
MyKind := GetTypeKind<TMethodProc>;
class function GetTypeKind<T>:TTypeKind;
var
TI: PTypeInfo;
begin
TI := TypeInfo(T);
...
end;
Run Code Online (Sandbox Code Playgroud)
我知道匿名方法背后有一些编译魔术.但我得到以下结果:
TI.TypeData.IntfParent == IInterface
TI.TypeData.IntfFlags == [(out of bounds)6]
Run Code Online (Sandbox Code Playgroud)
标志有一个意外的值,TIntfFlag有三个值,所以6是意外的.GUID也不是指导.它有一个相同的8个字节的重复集,大多数是00.例如(0,225,48,180,0,0,0,0,0,225,48,180,0,0,0,0)
匿名方法是否被排除在TypeInfo某些调整之外或者是否有用.
另外,(奇怪的)6是一个无证的特征,还是可以是任何值?
这没有什么异常的。
匿名方法实现为由编译器生成的接口,该接口具有Invoke()与匿名方法匹配相同签名的方法。这就是为什么TTypeKindis tkInterface和the IntfParentis的原因IInterface。
接口的后面是编译器生成的实现类,其中包含捕获的变量以及实现中的匿名方法的主体Invoke()。
的IntfFlags是TIntfFlagsBase,这是一个Set的TIntfFlag枚举值:
TIntfFlag = (ifHasGuid, ifDispInterface, ifDispatch);
Run Code Online (Sandbox Code Playgroud)
ifHasGuid
接口具有一个GUID(全局唯一标识符)。ifDispInterface
是一个调度接口。ifDispatch
可以调度。
A Set是值的位掩码。每个枚举值由掩码中的特定位表示。在内TIntfFlagsBase,第ifHasGuid0 ifDispInterface位,第1位和第ifDispatch2位。因此,启用110b的ifDispInterfaceand ifDispatch标志是数值6(),而不是ifHasGuid标志。因此,IntfGuid并没有有意义的值,但仍然TTypeData为了对齐目的而占用的空间。
更新:我使用XE2进行了测试,可以肯定的是,我看到的IntfFlags是TIntfFlag(6)按预期设置为序数64(如您所见),而不是序数6。我所看到的与您所看到的之间的唯一区别是,我看到的Guid完全为空(全零)。
更新:显然,对于启用了方法信息({$M+}指令)或代表匿名方法类型的接口,确实存在其他标志,这些标志在TIntfFlag枚举中未表示。我已经为此提交了一个错误报告:
RSP-24631:System.TypInfo.TIntfFlag枚举缺少标志
在这种情况下,TIntfFlag(6)是匿名方法的标志。
自从Delphi6以来,似乎似乎从未对TIntfFlag枚举进行过扩展(我认为那是在引入接口RTTI时)-我可以确认,至少由于XE带有$ M +的接口类型获得了第四个标志(将其称为ifHasMethodInfo)设置了。
如果类型是匿名方法类型...,则该集合中有第7个枚举值。我不知道置位5和6的情况。
...
我可以使用以下代码确认我的发现:
Run Code Online (Sandbox Code Playgroud)TIntfFlag = (ifHasGuid, ifDispInterface, ifDispatch);打印此:
IInterface [ifHasGuid] IInvokable [ifMethodInfo] IFoo [ifHasGuid,ifMethodInfo] TProc [ifAnonymousMethod] TFunc [ifAnonymousMethod] TMyProc [ifMethodInfo,ifAnonymousMethod] IBar [ifHasGuid,ifMethodInfo,ifAnonymousMethod]