对于需要类型" family"的一段代码。在泛型类型中,我尝试使用TypeInfo
来检索所需的信息。
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,0,0,0,0,225,48,180,0,0,0,0)< / p>
匿名方法是否从TypeInfo
中排除,或者对某些调整有用。
另外,(奇怪的)6是一个未记录的特征,还是可以是任何值?
答案 0 :(得分:3)
这没有什么不寻常之处。
匿名方法是作为编译器生成的接口实现的,该接口具有与匿名方法匹配相同签名的Invoke()
方法。这就是TTypeKind
为tkInterface
而IntfParent
为IInterface
的原因。
接口后面是编译器生成的实现类,它包含捕获的变量,以及Invoke()
实现中匿名方法的主体。
How are anonymous methods implemented under the hood?
IntfFlags
是TIntfFlagsBase
,Set
枚举值为TIntfFlag
:
TIntfFlag = (ifHasGuid, ifDispInterface, ifDispatch);
ifHasGuid
接口具有GUID(全局唯一标识符)。ifDispInterface
是一个调度接口。ifDispatch
可以派遣。
Set
是值的位掩码。每个枚举值由掩码中的特定位表示。在TIntfFlagsBase
内,ifHasGuid
为位0,ifDispInterface
为位1,ifDispatch
为位2.因此,数值为6(110b
)是启用ifDispInterface
和ifDispatch
标志,但不是ifHasGuid
标志。因此,IntfGuid
没有任何有意义的值,但仍会占用TTypeData
中的空格以进行对齐。
更新:我使用XE2进行了测试,果然,我看到IntfFlags
设置为序号64(TIntfFlag(6)
,如您所见),而不是序号6,如预期。我看到的和您看到的内容之间的唯一区别是,我看到Guid
完全为空(全为零)。