Originale-mail to me for new edition

 

Enumerated types

 

An enumerated type defines an ordered set of values by simply listing identifiers that denote these values. The values have no inherent meaning. To declare an enumerated type, use the syntax

type typeName = (val1, ..., valn)

where typeName and each val are valid identifiers. For example, the declaration

type Suit = (Club, Diamond, Heart, Spade);

defines an enumerated type called Suit whose possible values are Club, Diamond, Heart, and Spade, where Ord(Club) returns 0, Ord(Diamond) returns 1, and so forth.

When you declare an enumerated type, you are declaring each val to be a constant of type typeName. If the val identifiers are used for another purpose within the same scope, naming conflicts occur. For example, suppose you declare the type

type TSound = (Click, Clack, Clock);

Unfortunately, Click is also the name of a method defined for TControl and all of the objects in the VCL and/or CLX that descend from it. So if you’re writing an application and you create an event handler like

procedure TForm1.DBGrid1Enter(Sender: TObject);

var Thing: TSound;

begin

  ...

  Thing := Click;

  ...

end;

you’ll get a compilation error; the compiler interprets Click within the scope of the procedure as a reference to TForm’s Click method. You can work around this by qualifying the identifier; thus, if TSound is declared in MyUnit, you would use

Thing := MyUnit.Click;

A better solution, however, is to choose constant names that are not likely to conflict with other identifiers. Examples:

type

  TSound = (tsClick, tsClack, tsClock);

  TMyColor = (mcRed, mcBlue, mcGreen, mcYellow, mcOrange);

  Answer = (ansYes, ansNo, ansMaybe);

You can use the (val1, ..., valn) construction directly in variable declarations, as if it were a type name:

var MyCard: (Club, Diamond, Heart, Spade);

But if you declare MyCard this way, you can’t declare another variable within the same scope using these constant identifiers. Thus

var Card1: (Club, Diamond, Heart, Spade);

var Card2: (Club, Diamond, Heart, Spade);

generates a compilation error. But

var Card1, Card2: (Club, Diamond, Heart, Spade);

compiles cleanly, as does

type Suit = (Club, Diamond, Heart, Spade);

var

  Card1: Suit;

  Card2: Suit;

 

Enumerated types with explicitly assigned ordinality

By default, the ordinalities of enumerated values start from 0 and follow the sequence in which their identifiers are listed in the type declaration. You can override this by explicitly assigning ordinalities to some or all of the values in the declaration. To assign an 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 called 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, in effect, a subrange whose lowest and highest values correspond to the lowest and highest ordinalities of the constants in the declaration. In the example above, the Size type has 11 possible values whose ordinalities range from 5 to 15. (Hence the type array[Size] of Char represents an array of 11 characters.) Only three of these values have names, but the others are accessible through typecasts and through routines such as Pred, Succ, Inc, and Dec. In the following example, anonymous values in the range of Size are assigned to the variable X.

var X: Size;

X := Small;      // Ord(X) = 5

X := Size(6);    // Ord(X) = 6

Inc(X);          // Ord(X) = 7

Any value that isn’t explicitly assigned an ordinality has ordinality one greater than that of the previous value in the list. If the first value isn’t assigned an ordinality, its ordinality is 0. Hence, given the declaration

type SomeEnum = (e1, e2, e3 = 1);

SomeEnum has only two possible values: Ord(e1) returns 0, Ord(e2) returns 1, and Ord(e3) also returns 1; because e2 and e3 have the same ordinality, they represent the same value.

 

Topic groups

 

See also

Ordinal types: Overview

 

 

译文

 

枚举类型

 

枚举类型定义了一个有序的值的集合,这些值简单地用标识符列表表示,并且不需要有固定含义。声明枚举类型的语法是:

type typeName = (val1, ..., valn)

这里的类型名typeName和每个值val都是有效标识符。例如,声明

type Suit = (Club, Diamond, Heart, Spade);

定义了一个叫做Suit的枚举类型,Suit类型中可能的值是ClubDiamondHeartSpade,这里,Ord(Club)返回0Ord(Diamond)返回1,等等。

 

声明枚举类型时,可以声明每个值val作为类型typeName的常量。如果val标识符在相同的作用域中已经用于其他含义,那么将发生命名冲突。例如,假定声明了类型

type TSound = (Click, Clack, Clock);

不幸的是,Click也已作为TControl极其才VCL/CLX中的所有后裔的方法名被声明。因此,如果编写一个应用程序并创建一个事件句柄如

procedure TForm1.DBGrid1Enter(Sender: TObject);

var Thing: TSound;

begin

  ...

  Thing := Click;

  ...

end;

这将导致编译错误,因为编译器将把这里的Click作为对TFormClick方法的引用来解释。当然,可以通过限定词来回避,这里假如TSound是在单元MyUnit中声明的,那么可以写成

Thing := MyUnit.Click;

更好的解决办法是,选择不会与其他标识符冲突的常量名称。例如:

type

  TSound = (tsClick, tsClack, tsClock);

  TMyColor = (mcRed, mcBlue, mcGreen, mcYellow, mcOrange);

  Answer = (ansYes, ansNo, ansMaybe);

 

可以使用(val1, ..., valn)结构直接声明枚举类型,例如

var MyCard: (Club, Diamond, Heart, Spade);

但这样就不能在相同的作用域中再声明另一个变量使其具有相同的标识符。如

var Card1: (Club, Diamond, Heart, Spade);

var Card2: (Club, Diamond, Heart, Spade);

这将产生编译错误。而声明

var Card1, Card2: (Club, Diamond, Heart, Spade);

可以通过编译,相当于

type Suit = (Club, Diamond, Heart, Spade);

var

  Card1: Suit;

  Card2: Suit;

 

明确指定序号的枚举类型

缺省情况下,枚举值的序号从0开始,并且接下来的序列对应类型声明中相应的标识符。可以通过对部分或全部枚举值明确指定序号来忽略缺省序号。要对枚举值指定序号,则要再标识符后跟随 = constantExpression,这里 constantExpression是一个可以计算得到整数的常量表达式。例如

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

定义了一个叫做Size的枚举类型,该类型可能的值包括SmallMediumLarge,这里Ord(Small)返回5Ord(Medium)返回10Ord(Large)返回15

 

实际上,一个枚举类型就是一个子界,该子界的最小值和最大值对应于声明中常量的最小序号和最大序号。再上面的例子中,Size类型有11个可能的值,这些值的范围是515。(因此,类型array[Size] of Char表示的是一个含有11个字符的数组。)在这些值中,只有三个有名字,但其他的值通过类型转换和一些例程(如PredSuccIncDec)也是可访问的。下面的例子中,在Size类型范围之内的匿名值被赋给了变量X

var X: Size;

X := Small;      // Ord(X) = 5

X := Size(6);    // Ord(X) = 6

Inc(X);          // Ord(X) = 7

 

在枚举类型声明中,任何没有明确给出序号的值,其缺省序号比其前驱值大1。如果第一个值没有被指定序号,那么其序号为0。因此,对于给出的声明

type SomeEnum = (e1, e2, e3 = 1);

枚举类型SomeEnum仅有两个可能的值:Ord(e1) 返回0Ord(e2)返回1,并且Ord(e3)也返回1,因为e2e3具有相同的序号,所以他们表示相同的值。

 

主题组

 

相关主题

序数类型:概述