1.枚举
枚举是由程序员定义的类型,与结构一样。
枚举是值类型,直接存储它们的数据,不是分开存储成引用和数据。
枚举只是一种类型的成员:命名的整数值常量。成员声明之间逗号分隔。
例如:
enum TrafficLight
{
Green,
Yellow,
Red
}
使用关键字enum声明,后加枚举名称 TrafficLight,枚举值之间逗号分隔,枚举值使用大括号包裹。
每个枚举值默认为int.编译器对第一个成员赋值为0,后续每个成员赋值都比前一个多1.
测试:
Console.WriteLine($"{TrafficLight.Green}--{(int)TrafficLight.Green}");
输出:Green--0
Console.WriteLine($"{TrafficLight.Yellow}--{(int)TrafficLight.Yellow}");
Yellow--1
可把枚举值赋值给枚举类型变量。
TrafficLight TL = TrafficLight.Green;
TrafficLight TL2 = TL;
Console.WriteLine($"{TL2} --{(int)TL2}");
输出:Green --0
设置底层类型和显示值
类型可以是任何整数类型。尽管不能有重复名称,但是可以有重复值。
//等效
enum TrafficLight:int
{
Green =0,
Yellow =1,
Red=2
}
也可以自定义值:
enum TrafficLight:int
{
Green =1,
Yellow =3,
Red=5
}
给隐式成员编号
可显式给任何成员变量赋值,如果不初始化成员常量,编译器隐式给它赋初值。
enum Level
{
One =10,
Two,
Three=15,
Four,
Five=1
}
测试:
Console.WriteLine($"{(int)Level.One} {(int)Level.Two} {(int)Level.Three} {(int)Level.Four} {(int)Level.Five}");
输出:10 11 15 16 1
从输出可以看出,可任意给枚举成员变量指定整型值,其后的变量值自动加1,指定的值是可以跳变的,也可以默认。
2.位标志
单个字Single word的不同位表示一组开关标志的紧凑方法。成为标志字 flag word.
一般步骤:
(1) 确定需要多少个标志位,选择一种有足够多的位的无符号类型来保存它。
(2) 确定每个位位置代表什么,并给它们一个名称。
(3) 使用按位或OR 运算符在持有该标志位的字中设置适当的位
(4) 使用按位与 AND运算符或HasFlag方法检查是否设置了特定位标志
从C# 7.0开始,可以使用二进制表示法
使用Flags特性可带来一些便利。
[Flags]
enum CardSettings:uint
{
SingleDeck = 0x01,
LargePictures = 0x02,
FancyNumbers = 0x04,
Aniamation = 0x08
}
测试代码:
CardSettings settings = CardSettings.SingleDeck | CardSettings.LargePictures;
Console.WriteLine($"{settings} {(uint)settings}"); //输出:3
使用Flags 属性的标志枚举变量可以使用逻辑位运算。
如果指定的标志位有值返回true,否则返回false
Console.WriteLine(settings.HasFlag(CardSettings.SingleDeck));//true
Console.WriteLine(settings.HasFlag(CardSettings.Aniamation));//false
还可以检测多个标志位:
Console.WriteLine(settings.HasFlag(CardSettings.SingleDeck|CardSettings.FancyNumbers)); //False
Console.WriteLine(settings.HasFlag(CardSettings.SingleDeck | CardSettings.LargePictures)); //True
另一种判断方法是使用按位与运算,将该标志字与标志位相与,然后与位标志比较。
例如:检查是否设置了FancyNumbers
CardSettings settings = CardSettings.SingleDeck | CardSettings.LargePictures;
bool useFancyNumber = (settings & CardSettings.FancyNumbers) == CardSettings.FancyNumbers;
Console.WriteLine(useFancyNumber);
输出: False
CardSettings settings = CardSettings.SingleDeck | CardSettings.FancyNumbers;
bool useFancyNumber = (settings & CardSettings.FancyNumbers) == CardSettings.FancyNumbers;
Console.WriteLine(useFancyNumber);
输出:True
Flags特性
Flags特性不会改变结算结构,却提供了一些方便的特性。
可以组成成位标志。ToString( )方法提供了更多的格式化信息,
CardSettings settings = CardSettings.SingleDeck | CardSettings.FancyNumbers;
Console.WriteLine(settings.ToString());
输出:
SingleDeck, FancyNumbers
settings = CardSettings.Aniamation;
Console.WriteLine(settings.ToString());
输出:
Aniamation
3.关于枚举的更多内容
枚举只有单一的成员类型:声明的成员常量
不能对成员使用修饰符
由于成员是静态的,即使在没有枚举类的变量时也可以访问它们。
枚举类型.成员变 访问方式
其它一些枚举类型的静态方法:GetNames,GetName,GetValues
Console.WriteLine($"{Enum.GetName(typeof(TrafficLight),1)}"); //Green
Console.WriteLine($"{Enum.GetName(typeof(TrafficLight), 3)}"); //Yellow
foreach (var n in Enum.GetNames(typeof(TrafficLight)))
{
Console.WriteLine(n);
}
输出:
Green
Yellow
Red
foreach (var item in Enum.GetValues(typeof(TrafficLight)))
{
Console.WriteLine((int)item);
}
输出:
1
3
5