Attributes and Array of Const
How annoying!
type
Values = class(TCustomAttribute)
Constructor Create(const Name: String; Params: array of const);
end;
TMyClass = class
…
public
[Values(‘Default’, [1, 2.0, ‘three’])] <– E2026
property List1: TMyVariantList;
E2026 – Constant expression expected
and what a tragic help entry :/
http://docwiki.embarcadero.com/RADStudio/XE5/en/E2026_Constant_expression_expected_(Delphi)
Question: In what way is that array not constant at compile time?

Does the following work?
Constructor Create(const Name: String; const Params: array of const);
Nope. Same error, same spot.
Generics isn’t Delphi’s strongest point, I just did a quick test with “TVariantArray = array of variant”, but I got incompatible with set, the “TVariantArray.Create(1, 2, ‘test’)” doesn’t work, so, I guess we’re out of luck on this one… — ran the test in D2010
Note that this is Const, not variant.
It’s perfectly legal to have a
procedure TMyClass.Create(const aList: array of const);
but it’s not supported for attributes 🙁
Perhaps our resident Generics and RTTI guru Stefan Glienke knows of a QC, or have insights to why this is not possible?
Lars Fosdal I’ve noticed and am aware of difference, but I thought a hackish “array of variant” might work, apparently not… ):
Reported it as http://qc.embarcadero.com/wc/qcmain.aspx?d=123972
Update
It also fails for explicitly typed arrays
type
Values = class(TCustomAttribute)
Constructor Create(const Name: String; const Params: array of const);
end;
Strings = class(TCustomAttribute)
Constructor Create(const Name: String; const Params: array of String);
end;
const
SomeStrings : Array[0..2] of String = (‘1’, ‘2.0’, ‘three’);
type
TMyClass = class
private
FList: TStringList;
public
[Strings(‘Default’, SomeStrings)] //<– E2026 Constant expression expected
[Strings(‘Default’, [‘1’, ‘2.0’, ‘three’])] //<– E2026 Constant expression expected
[Values(‘Default’, [1, 2.0, ‘three’])] //<– E2026 Constant expression expected
property List: TStringList read FList;
end;
Lars Fosdal whatever, good thing we got the monkey! /:
Lars Fosdal IIRC what you do there is giving an OpenArray to the constructor. For an OpenArray it puts the adress of the array as parameter into the constructor(which means it’s some kind of @CompilerGeneratedArray). And those arrayvalues are pushed to the stack, which does NOT exist here(as far as i know)
But runtime adress evaluation is not possible for Attribute constructors.
at least as described here:
http://docwiki.embarcadero.com/RADStudio/XE5/en/Annotating_Types_and_Type_Members#Allowed_Parameters
Mentioned on stackoverflow:
http://stackoverflow.com/questions/8976150/tcustomattribute-constant-expression-expected-compile-error
But i do NOT know for sure. Just a guess. Take this info with caution 😉
Typed consts are not really consts, they are just variables with write protection.
Just try this:
type
MyAttribute = class(TCustomAttribute)
constructor Create(const AInteger: Integer);
end;
const
CMyInteger: Integer = 3;
type
TForm = class(TForm)
private
[My(CMyInteger)]
procedure Foo;
end;
You will get the compile error E2026.
If you just write CMyInteger = 3; everything compiles.
Fabian S. Biehn “Typed consts are not really consts, they are just variables with write protection.”
unless you turn on “writable constants” flag on (:
Fabian S. Biehn – In the initial post, the constants are not typed. I guess the compiler can’t handle building lists of constant references within the attribute definition, for some reason.
Can arrays even be declared not typed? I can write
const CMyStringArray: array[0..1] of Integer = (1, 2);
but not
const CMyStringArray = (1, 2);
Are there other ways?
I think your [1, 2.0, ‘three’] is also an typed array.
That [1, 2.0, ‘three’] kind of array is not a const. I need to dig into it, but I think at run-time it is assembled code wise.
array of const is an open array of TVarRec. Read Rudys article about it: http://rvelthuis.de/articles/articles-openarr.html.
open arrays cannot be const
Try array of string it doesn’t work either.
It still feels illogical.
It’s an array of constant values, defined at compile time, and not possible to reference by other code.
Elsewhere in the code – they would for all practical purposes be constants.
The thing is how the compiler handles open array parameters and how arguments to the attribute constructor are stored. I am not saying it is impossible to implement but the current mechanics don’t support it.
I wonder if this QC entry went the way of the Dodo…
Time to update it with a TArray example in the QP?
Ah, there is one already: quality.embarcadero.com – Log in – Embarcadero Technologies