Array declaration with error enums in Delphi XE6

When I declare an enum like this:

TConfigBaudRate = (br9600 = 6, br19200 = 8);

      

and try using this enum with an array, for example:

const
    CBaudRates: array [TConfigBaudRate] of string = ('9600', '19200');

      

Delphi is giving me back the following error:

E2072 Number of elements (2) different from declaration (3)

But if I declare TConfigBaudRate with no values ​​or a value for the first item, it works.

Delphi seems to create one item from the number 7. Is this a normal Delphi characteristic? I couldn't find any links.

+3


source to share


3 answers


This is a documented behavior.

From Simple types - enumerated types with an explicitly assigned ordinal : ( emphasis mine )



By default, ordinal numbers of enumerated values ​​start at 0 and are followed by the sequence in which their identifiers are listed in the type declaration. You can override this by explicitly assigning sequence numbers to some or all of the values ​​in the declaration. To assign ordinality to a value, follow its identifier with = constantExpression, where constantExpression is a constant expression that evaluates to an integer. For example:

type Size = (Small = 5, Medium = 10, Large = Small + Medium);

      

defines a type named Size whose possible values ​​include Small, Medium, and Large, where Ord (Small) returns 5, Ord (Medium) returns 10, and Ord (Large) returns 15.

An enumerated type is essentially a sub-range, the lowest and highest values ​​of which correspond to the lowest and highest ordinal numbers of the constants in the declaration. In the previous example, the size type has 11 possible values, the orders of which range from 5 to 15. (Therefore, the [Size] array of Char represents an array of 11 characters.) Only three of these values ​​have names, but others are accessible through type tricks and using routines such as Pred, Succ, Inc and Dec. ... The following example assigns "anonymous" values ​​in the Size range to the variable X

var 
  X: Size; 
  X := Small;   // Ord(X) = 5 
  X := Size(6); // Ord(X) = 6 
  Inc(X);       // Ord(X) = 7

      

So for your example, although you only used two values ​​(6 and 8), 7 is an included value even if unnamed, since it falls in the assigned orders, in the same way described array[Size] of Char

would represent an array of 11 characters.

+10


source


The problem is that your enum type specifies ordinal values, and you missed some values ​​using an explicitly assigned order of actions .

Key quote from the documentation :

An enumerated type is essentially a subrange whose lowest and highest values ​​correspond to the lowest and highest ordinal numbers of the constants in the declaration.

This program shows that ord(low(TConfigBaudRate))

- 6

, and ord(high(TConfigBaudRate))

- 8

.

{$APPTYPE CONSOLE}

type
  TConfigBaudRate = (br9600 = 6, br19200 = 8);

begin
  Writeln(ord(low(TConfigBaudRate)));
  Writeln(ord(high(TConfigBaudRate)));
end.

      

Output



6
8

All this means that your array contains three elements with orders 6, 7, and 8. You only specified two values ​​in your constant and that is what the compiler error tells you.

You can solve the compiler error by specifying three values, for example:

const
  CBaudRates: array [TConfigBaudRate] of string = ('9600', '', '19200');

      

However, I believe this whole experience is a language way of telling you to stop using an explicitly assigned residency.

+5


source


In addition to the answers already provided ...

In Delphi, array indices must form a contiguous range of ordinals. Ad:

CBaudRates: array [TConfigBaudRate] of string;

      

Equivalent to:

CBaudRates: array [Ord(Low(TConfigBaudRate))..Ord(High(TConfigBaudRate))] of string;

      

Or:

CBaudRates: array [6..8] of string;

      

And that will obviously include item 7 - even if not in use.

The core Delphi language constructs have no facility for defining a "discrete array" (that is, with spaces). This is why things like sparse arrays require higher level data structures.

Now, while it is theoretically possible for the compiler to render inside 6 == 0

and out 8 == 1

(allowing an array declaration to only contain 2 elements), that would be impractical and inefficient.

+2


source







All Articles