第 47 讲:枚举(三):其它枚举相关的问题
前面已经说过了枚举的基本使用方式,以及运算符的使用。下面讲一些有关枚举类型的、前面没有提到的问题。
Part 1 枚举字段是否定义的问题
我们经常使用枚举类型把数值取出。但问题是,前文我们在表达枚举类型和整数类型进行互相转换的时候,尚未提及整个问题,那就是:如果我们将一个不存在于枚举类型里的特征值强制转换为枚举类型,那么使用它是成功的吗?是抛异常呢,还是其它情况呢?
假设我有一个枚举类型,只包含两个数值:
Gender
实际上,没有任何事发生。赋值是成功的,也不会有异常,也不会中断程序,更不会出现别的现象。这样的赋值唯一和正常范围的特征值表现出来效果不一样的地方是调用 ToString
方法之后。
前者的 0 特征值对应了 Gender
类型的 Male
,因此这么转换最后输出的是 Male
也就是说,如果对于一个没有对应字段的枚举类型变量进行 ToString
输出的话,实际上输出的是特征值本身;如果有的话,实际上输出的就是这个字段的名字。这是两种情况的不同点,其它的使用完全都是一样的,不会因为超出枚举定义范围而直接告诉你不能这么用,C# 没有必要限制得这么死,毕竟……没定义又不是什么无伤大雅的事情。
Part 2 特征值表达式
前文我们学习了如何使用位运算来对特殊的枚举类型进行操作。不过,实际上 C# 甚至允许你直接在特征值赋值的时候书写表达式。比如这样:
不过这里稍微注意一点。我们之前说过,<<
和 >>
是枚举类型无法使用的运算符,但是在特征值赋值的表达式里,我们可以用,但右侧必须是一个 int
类型的字面量。
比如这样的枚举,每一个字段都是前一个字段的特征值的两倍。
但是我们在平时使用的时候,我们无法使用 <<
运算符,因为这是 C# 规定禁止使用的、为数不多的运算符之一:
Part 3 负数特征值的枚举转换
可能你使用过带符号类型的整数作为特征值的基本类型表示在枚举类型的“继承关系”上。实际上,默认情况下枚举类型是使用 int
这个带符号的类型作为特征值类型的。
那么,如果我赋值 -1 作为某字段的特征值的话,我要想使用它,你可能会这么写代码:
TestEnum
另外在 C# 的字面量系统里,数据使用字面量有很复杂的转换关系(什么“不超过一定范围的字面量,虽然是 int
类型也可以表示为较小数据类型”之类的规则)。正是因为这些规则的约束,一旦放开 -1 不添加括号直接转换的话,就会和这些细节产生一定的语义冲突。为了避免这一点,C# 不得不让你添加这个小括号,告诉你要想是负数枚举特征值的话,就必须加了小括号后再来强制转换。