class function GetTypeKind<T>:TTypeKind;
对于大多数类型,我可以解决这个问题.但匿名方法类型表现出意外.
我有一个匿名方法类型定义为:
TMethodProc = reference to procedure;
我试着获取类型信息:
MyKind := GetTypeKind<TMethodProc>; class function GetTypeKind<T>:TTypeKind; var TI: PTypeInfo; begin TI := TypeInfo(T); ... end;
我知道匿名方法背后有一些编译魔术.但我得到以下结果:
TI.TypeData.IntfParent == IInterface TI.TypeData.IntfFlags == [(out of bounds)6]
标志有一个意外的值,TIntfFlag有三个值,所以6是意外的. GUID也不是指导.它有一个相同的8个字节的重复集,大多数是00.例如(0,225,48,180,0)
匿名方法是从TypeInfo中排除还是对某些调整有用.
另外,(奇怪的)6是一个无证的特征,还是可以是任何值?
解决方法
匿名方法是作为编译器生成的接口实现的,该接口具有与匿名方法匹配相同签名的Invoke()方法.这就是为什么TTypeKind是tkInterface而IntfParent是IInterface.
接口后面是编译器生成的实现类,它包含捕获的变量,以及Invoke()实现中的匿名方法的主体.
How are anonymous methods implemented under the hood?
IntfFlags是TIntfFlagsBase
,这是TIntfFlag
个枚举值的Set
:
TIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch);
ifHasGuid
Interface has a GUID (Globally Unique Identifier).ifDispInterface
Is a dispatch interface.ifDispatch
Can be dispatched.
Set是值的位掩码.每个枚举值由掩码中的特定位表示.在TIntfFlagsBase中,ifHasGuid为bit 0,ifDispInterface为bit 1,ifDispatch为bit 2.因此,数字值6(110b)将是ifDispInterface和ifDispatch标志启用,但不是ifHasGuid标志.因此,IntfGuid没有任何有意义的值,但仍占用TTypeData中的空间以进行对齐.
更新:我测试了XE2,果然,我看到IntfFlags设置为序数64(TIntfFlag(6),如你所见)而不是序号6,如预期的那样.我看到的和你看到的唯一区别是我看到Guid是完全空的(全为零).