Attributes and Array of Const

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?

Comments

  1. Does the following work?

    Constructor Create(const Name: String; const Params: array of const);

    ReplyDelete
  2. 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

    ReplyDelete
  3. 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?

    ReplyDelete
  4. Lars Fosdal I've noticed and am aware of difference, but I thought a hackish "array of variant" might work, apparently not... ):

    ReplyDelete
  5. 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;

    ReplyDelete
  6. Lars Fosdal whatever, good thing we got the monkey! /:

    ReplyDelete
  7. 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.

    ReplyDelete
  8. Fabian S. Biehn "Typed consts are not really consts, they are just variables with write protection."
    unless you turn on "writable constants" flag on (:

    ReplyDelete
  9. 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.

    ReplyDelete
  10. 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.

    ReplyDelete
  11. 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.

    ReplyDelete
  12. 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.

    ReplyDelete
  13. 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.

    ReplyDelete
  14. 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.

    ReplyDelete
  15. I wonder if this QC entry went the way of the Dodo...
    Time to update it with a TArray example in the QP?

    ReplyDelete

Post a Comment