第12章 枚举 笔记 25.06.16
12.1 枚举
枚举由程序员定义的类型,与类、结构一样。
- 枚举是值类型,直接存储对应数据
- 只有一种类型的成员:命名的整数值常量。
// TrafficLight 枚举
enum TrafficLight
{
Green, //Comma separated—no semicolons
Yellow, //Comma separated—no semicolons
Red
}
每个枚举成员都被赋予一个底层整数类型,默认为int
默认情况下,编译器对第一个成员赋值为 0,后续成员的值依次递增 1。
TrafficLight t1 = TrafficLight.Green;
TrafficLight t2 = TrafficLight.Yellow;
TrafficLight t3 = TrafficLight.Red;
Console.WriteLine($"{ t1 },\t{(int) t1 }");
Console.WriteLine($"{ t2 },\t{(int) t2 }");
Console.WriteLine($"{ t3 },\t{(int) t3 }\n");
// output
Green, 0
Yellow, 1
Red, 2
可以把枚举值赋给枚举类型变量,打印时将打印成员名称。
class Program
{
static void Main()
{
//Type Variable Member
TrafficLight t1 = TrafficLight.Red; // Assign from member
TrafficLight t2 = TrafficLight.Green; // Assign from member
TrafficLight t3 = t2; // Assign from variable
Console.WriteLine(t1);
Console.WriteLine(t2);
Console.WriteLine(t3);
}
}
// output
Red
Green
Green
12.1.1 设置底层类型和显式值
将冒号和类型名放在枚举名之后,可以设置底层类型:
enum TrafficLigh : ulong
{
// ...
}
成员常量的值可以是底层类型的任何值。 枚举类型不能有重复的名称,但可以有重复的值。
enum TrafficLight
{
Green = 10,
Yellow = 15, // Duplicate values
Red = 15 // Duplicate values
}
默认赋值、显式赋值
// 默认
enum TrafficLight
{
Green,
Yellow,
Red
}
enum TrafficLight : int
{
Green = 0,
Yellow = 1,
Red = 2
}
12.1.2 隐式成员编号
可以显示地给任何成员常量赋值。
如果不初始化成员常量,编译器将隐式地给他赋值。
enum CardSuit {
Hearts, // 0 - Since this is first
Clubs, // 1 - One more than the previous one
Diamonds, // 2 - One more than the previous one
Spades, // 3 - One more than the previous one
MaxSuits // 4 - A common way to assign a constant
} // to the number of listed items
enum FaceCards {
// Member // Value assigned
Jack = 11, // 11 - Explicitly set
Queen, // 12 - One more than the previous one
King, // 13 - One more than the previous one
Ace, // 14 - One more than the previous one
NumberOfFaceCards = 4, // 4 - Explicitly set
SomeOtherValue, // 5 - One more than the previous one
HighestFaceCard = Ace // 14 - Ace is defined above
}
12.2 位标志
单个字的不同位作为表示一组开/关标准的紧凑方法,称为标志字。
枚举可实现位标志的应用:
-
选取足够长度的无符号类型作为枚举底层类型。
-
确定每个位置代表的含义。
- 通常使用十六进制法。
-
使用 或运算符 在字中设置位
-
使用 与运算符 检查是否设置了特定的位标准
C# 7.0 后可以使用二进制表示法。
使用Flags特性装饰枚举
[Flags]
enum CardDeckSettings : uint
{
SingleDeck = 0b0001, // 位 0
LargePictures = 0b0010, // 位 1
FancyNumbers = 0b0100, // 位 2
Animation = 0b1000, // 位 3
}
使用按位或(|
)运算符设置标志位。
CardDeckSettings ops = CardDeckSettings.SingleDeck
| CardDeckSettings.FancyNumbers
| CardDeckSettings.Animation ;
使用按位与(&
)运算符或 HasFlag
方法检查是否设置了特定标志位。
HasFlag
方法,如果设置了对应的位标志,返回true,否则返回false
bool useFancyNumbers = ops.HasFlag(CardDeckSettings.FancyNumbers);
- 按位与
&
。
bool useFancyNumbers =
(ops & CardDeckSettings.FancyNumbers) == CardDeckSettings.FancyNumbers;
12.2.1 Flags 特性
Flags 特性不改变计算结果,其作用如下:
- 通知编译器等工具,该枚举可以组成位标志。
- 允许 ToString 方法提供更多的格式化信息。
// [Flags]
enum CardDeckSettings : uint
{
SingleDeck = 0x01, // bit 0
LargePictures = 0x02, // bit 1
FancyNumbers = 0x04, // bit 2
Animation = 0x08 // bit 3
}
class Program {
static void Main( ) {
CardDeckSettings ops;
ops = CardDeckSettings.FancyNumbers; // Set one flag.
Console.WriteLine( ops.ToString() );
// Set two bit flags.
ops = CardDeckSettings.FancyNumbers | CardDeckSettings.Animation;
Console.WriteLine( ops.ToString() ); // Print what?
}
}
// 如果没有 `[Flags]` 特性 输出
FancyNumbers
12
// 加上特性后,ToString 方法返回结果将会发生改变
FancyNumbers
FancyNumbers, Animation
12.2.2 使用位标志的示例
[Flags]
enum CardDeckSettings : uint
{
SingleDeck = 0x01, // bit 0
LargePictures = 0x02, // bit 1
FancyNumbers = 0x04, // bit 2
Animation = 0x08 // bit 3
}
class MyClass {
bool UseSingleDeck = false,
UseBigPics = false,
UseFancyNumbers = false,
UseAnimation = false,
UseAnimationAndFancyNumbers = false;
public void SetOptions( CardDeckSettings ops ) {
UseSingleDeck = ops.HasFlag( CardDeckSettings.SingleDeck );
UseBigPics = ops.HasFlag( CardDeckSettings.LargePictures );
UseFancyNumbers = ops.HasFlag( CardDeckSettings.FancyNumbers );
UseAnimation = ops.HasFlag( CardDeckSettings.Animation );
CardDeckSettings testFlags =
CardDeckSettings.Animation | CardDeckSettings.FancyNumbers;
UseAnimationAndFancyNumbers = ops.HasFlag( testFlags );
}
public void PrintOptions( )
{
Console.WriteLine( "Option settings:" );
Console.WriteLine($" Use Single Deck - { UseSingleDeck }");
Console.WriteLine($" Use Large Pictures - { UseBigPics }");
Console.WriteLine($" Use Fancy Numbers - { UseFancyNumbers }");
Console.WriteLine($" Show Animation - { UseAnimation }");
Console.WriteLine( " Show Animation and FancyNumbers – {0}",
UseAnimationAndFancyNumbers );
}
}
class Program
{
static void Main( )
{
MyClass mc = new MyClass( );
CardDeckSettings ops = CardDeckSettings.SingleDeck
| CardDeckSettings.FancyNumbers
| CardDeckSettings.Animation;
mc.SetOptions( ops );
mc.PrintOptions( );
}
}
// output
Option settings:
Use Single Deck - True
Use Large Pictures - False
Use Fancy Numbers - True
Show Animation - True
Show Animation and FancyNumbers - True
12.3 关于枚举的更多内容
枚举只有单一的成员类型,声明的成员常量。
- 成员不能有修饰符。
- 枚举成员的可访问性默认和枚举本身相同。
- 成员是静态的,可以随时访问。
// TrafficLight 枚举
static void Main()
{
Console.WriteLine($"{ TrafficLight.Green }");
Console.WriteLine($"{ TrafficLight.Yellow }");
Console.WriteLine($"{ TrafficLight.Red }");
}
访问枚举的成员有两种方法:
使用类型名称,
C# 6.0 后,可以使用 using static 来省略枚举名称。
using static TrafficLight;
using static System.Console;
// ...
static void Main()
{
WriteLine( $"{ Green }" );
WriteLine( $"{ Yellow }" );
WriteLine( $"{ Red }" );
}
比较不同的枚举类型会导致编译时错误。
enum FirstEnum // First enum type
{
Mem1,
Mem2
}
enum SecondEnum // Second enum type
{
Mem1,
Mem2
}
class Program
{
static void Main()
{
if (FirstEnum.Mem1 < FirstEnum.Mem2) // OK--members of same enum type
Console.WriteLine("True");
// 会报错
if (FirstEnum.Mem1 < SecondEnum.Mem1) // Error--different enum types
Console.WriteLine("True");
}
}
Enum类型的静态方法:
GetName方法 以一个枚举类型和一个整数为参数,返回相应的枚举成员的名称
GetNames方法 以一个枚举类型对象为参数,返回该枚举中所有成员的名称。
enum TrafficLight
{
Green,
Yellow,
Red
}
class Program
{
static void Main()
{
Console.WriteLine( "Second member of TrafficLight is {0}\n",
Enum.GetName( typeof( TrafficLight ), 1 ) );
foreach ( var name in Enum.GetNames( typeof( TrafficLight ) ) )
Console.WriteLine( name );
}
}
// output
Second member of TrafficLight is Yellow
Green
Yellow
Red