第12章 枚举 笔记

第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 位标志

单个字的不同位作为表示一组开/关标准的紧凑方法,称为标志字。

枚举可实现位标志的应用:

  1. 选取足够长度的无符号类型作为枚举底层类型。

  2. 确定每个位置代表的含义。

    • 通常使用十六进制法。
  3. 使用 或运算符 在字中设置位

  4. 使用 与运算符 检查是否设置了特定的位标准

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值