Annotating Types and Type Members

From RAD Studio
Jump to: navigation, search

Go Up to Attributes (RTTI)


This topic describes the syntax and rules appropriate when annotating a type or a member with an attribute.

General Syntax

To annotate a Delphi type or a member, such as a class or a class member, you must precede the declaration of that type by the name of the attribute class between brackets:

[CustomAttribute]
TMyClass = class;

If the name of the attribute class ends in "Attribute", you can also omit the "Attribute" suffix:

[Custom]
procedure DoSomething;

Having a set of parenthesis after the attribute class name is also a valid syntax:

[Custom()]
TMyRecord = record;

Some attributes accept parameters. To pass arguments to your attribute, use the same syntax as you use for method calls:

[Custom(Argument1, Argument2, )]
TSimpleType = set of (stOne, stTwo, stThree);

To annotate a single type with several attributes, you can either use several sets of brackets:

[Custom1]
[Custom2(MyArgument)]
FString: String;

Or use comma-separated attributes between a single set of brackets:

[Custom1, Custom2(MyArgument)]
function IsReady: Boolean;

You Can Only Use Constant Expressions as Attribute Parameters

An attribute that is annotated to a type or a member is inserted into the RTTI information block in the generated binary. The emitted information includes:

  • The class type of the attribute.
  • The pointer to the selected constructor.
  • A list of constants that are later passed to the attribute constructor.

The values passed to the constructor of the attribute must be constant expressions. Because those values must be embedded directly into the resulting binary, it is impossible to pass an expression that requires run-time evaluation. This raises a few limitations to the information that can be passed to the attribute at compile time:

The following code exemplifies the case in which the compiler does not compile the annotation:

var
    a, b: Integer;
type
    [SomeAttribute(a + b)]
    TSomeType = record
    // …
    end;

In the previous example, the constructor of SomeAttribute requires an integer value. The passed expression requires a run-time evaluation of a + b. The compiler emits a compile-time error because it expects a constant expression.

The code below shows an accepted expression:

const
    a = 10;
    b = 20;
type
    [SomeAttribute(a + b)]
    TSomeType = record
    // …
    end;

The values of a and b are known at compile time; thus, the constant expression is evaluated directly.

See Also