给出以下代码片段:
type
MyIntf = interface
['{C6184693-663E-419F-B2DA-4DA1A0E33417}']
procedure Foo;
end;
InvisiblePropInterfaces = class(TCustomAttribute)
private
FGUIDS: array of TGUID;
public
constructor Create(const GUIDS: array of TGUID);
end;
[InvisiblePropInterfaces([MyIntf])] // <-- Constant expression expected error
TMyClass = class(TInterfacedObject, MyIntf)
procedure Foo;
end;
为什么编译器认为这不是常量表达式? 但鉴于我使用这样的InvisiblePropInterfaces,编译器很高兴吗?
...
var
I: InvisiblePropInterfaces;
begin
I:= InvisiblePropInterfaces.Create([MyIntf]);
...
答案 0 :(得分:7)
attributes documentation的相关部分是:
重要的是要理解传递给属性构造函数的值必须是常量表达式。因为这些值必须直接嵌入到生成的二进制文件中,所以无法传递需要运行时评估的表达式。这对在编译时可以传递给属性的信息提出了一些限制:
- 只允许使用常量表达式,包括集合,字符串和序数表达式。
- out和var参数不能使用,因为它们需要运行时评估传递参数的地址。
- 无法使用Addr()内在函数和@运算符。
- TypeInfo()运算符可用于传递类型信息,因为RTTI块地址在编译时是已知的。
- 允许类引用,因为元类地址(如TypeInfo()的情况)在编译时是已知的。
关键是constant expression是一个技术Pascal术语,与常量不同。我怀疑这是混乱的根源。
由于无法将一个常量表达式传递给TGUID
,因此您的属性不通。实际上,有一个可以传递给开放数组参数的常量表达式是不可能的。
我认为你可以使用GUID
的字符串表示来解决这个难题,但是这会让你感到麻烦复制并且无法传递GUID数组。
答案 1 :(得分:1)
这是一个已知的限制。 TGUID被声明为记录类型,无法创建记录常量表达式。