变量的更多内容-复杂的变量类型-枚举
到目前为止,介绍的都是C#提供的简单变量类型。还有3个略复杂(但非常有用)的变量,如下所示:
*枚举
*结构
*数组
今天主讲枚举,每种类型(除了string外)都有明确的取值范围。诚然,有些类型(如double)的取值范围非常大,可以看作是连续的,但其中的数值总是固定的。最简单的示例是bool类型,它只有true或false。
有时候,我们希望变量提取的是一个固定集合中的值。例如,orientation类型可以存储north,south,east或west中的一个值。此时,就可以使用枚举类型。枚举就可以完成这个orientation类型的任务:它们允许定义一个类型,其中包含提供的限定值集合中的一个值。
所以,需要创建自己的枚举类型orientation,它可以从上述的4个值中提取一个值。注意这是一个附加的步骤——不是仅仅声明一个给定类型的变量,而是声明和描述一个用户定义的类型,再声明这个新类型的变量。
枚举可以使用enum关键字来定义,如下所示:
enum typeName
{
value1,
value2,
value3,
...
valueN
}
接着声明这个新类型的变量:
typeName varName;
并赋值:
varName = typeName.value;
枚举使用一个基本类型来存储。枚举类型可以提取的每个值都存储为该基本类型的一个值,在默认情况下,该类型为int。在枚举声明中添加类型,就可以指定其他基本类型:
enum typeName : underlyingType
{
value1,
value2,
value3,
...
valueN
}
枚举的基本类型可以是byte,sbyte,short,ushort,int,uint,long和ulong。
在默认情况下,每个值都会根据定义的顺序(从0开始),自动赋给对应的基本类型值。这意味着value1的值是0,value2的值是1,value3的值是2等。可以重写这个赋值过程:使用=运算符,并制定每个枚举的实际值:
enum typeName : underlyingType
{
value1 = actualVal1,
value2 = actualVal2,
value3 = actualVal3,
...
valueN = actualValN,
}
另外,还可以使用一个值作为另一个枚举的基础值,为多个枚举制定相同的值:
enum typeName :underlyingType
{
value1 = actualVall,
value2 = value1,
value3,
...
valueN = actualValN
}
没有赋值的任何值都会获得一个初始值,这里使用的值是从此最后一个明确声明的值大1开始的序列。例如,在上面的代码中,value3的值是value + 1。
注意这可能会产生预料不到的问题,在一个定义如value2 = value1后指定的值可能与其他值相同。例如,在下面的代码中,value4的值与value2相同。
enum typeName : underlyingType
{
value1 = actualVal1,
value2,
value3 = vale1,
value4,
...
valueN = actualValN
}
当然,如果这正是希望的结果,则代码就是正确的。
还要注意,以迂回方式赋值可能会产生错误,例如:
enum typeName : underlyingType
{
value1 = value2,
value2 = value1
}
下面看一个例子,其代码定义了一个枚举orientation,然后演示它的用法。
using System.Collections.Generic;
using System.Text;
namespace enumerate
{
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west =4
}
class Program
{
static void Main(string[] args)
{
orientation myDirection = orientation.north;
Console.WriteLine("myDirection = {0}", myDirection);
Console.ReadKey();
}
}
}
当然你也可以修改部分代码,代码如下:
string directionString;
orientation myDirection = orientation.north;
Console.WriteLine("myDirection = {0}", myDirection);
directionByte = (byte)myDirection;
directionString = Convert.ToString(myDirection);
Console.WriteLine("byte equivalent = {0}", directionByte);
Console.WriteLine("string equivalent = {0}", directionString);
Console.ReadKey();
示例的说明
这段代码定义并使用了一个枚举类型orientation。首先要注意的是,类型定义代码放在命名空间中,而没有与其他代码放在一起,是因为在运行期间,定义代码并不是像执行应用程序中的代码那样一行一行的执行。应用程序是从已经习惯的位置开始执行的,并可以访问新类型,因为它属于同一个命名空间。
这个例子的第一个迭代演示了创建新类型的变量,给它赋值以及把它输出到屏幕上的基本方法。
接着修改代码的部分,把枚举值转换为其他类型。注意这里必须使用显示转换。即使orientation的基本类型是byte,仍必须使用(byte)数据类型转换,把myDirection的值转换为byte类型。
directionByte = (byte)myDirection;
如果把byte类型转换为orientation,也需要进行显示转换,例如,可以使用下述代码把byte变量myByte转换为orientation,并把这个值赋给myDirection:
myDirection = (orientation)myByte;
这里必须小心,因为并不是所有byte类型变量的值都可以映射为已定义的orientation值。Orientation类型可以存储其他byte值,所以不会直接产生一个错误,但会在应用程序的后面违反逻辑。
要获得枚举的字符串值,可以使用Convert.ToString():
directionString = Convert.ToString(myDirection);
使用(string)数据类型转换是不行的,因为需要进行的处理并不仅仅是把存储在枚举变量中的数据放在string变量中,而是更复杂一些。
另外,还可以使用变量本身的ToString()命令。下面的代码与使用Convert.ToString()的效果相同:
directionString = myDirection.ToString();
也可以把string转换为枚举值,但其语法略复杂一些。有一个特定的命令用于这种类型的转换,即Enum.Parse(),其使用方式如下:
(enumerationType)Enum.Parse(typeof(enumerationType),enumerationValueString);
它使用了另一个运算符typeof,可以得到操作数的类型。对orientation类型使用这个命令,如下所示:
string myString = "north";
orientation myDirection = (orientation)Enum.Parse(typeof(orientation),myString);
当然,并不是所有的字符串值都会映射为一个orientation值。如果一个值不能映射为枚举值中的一个,就会产生错误。与C#中的其他值一样,这些值是区分大小写的,否则就会产生错误。