Loading

C#教程 - 枚举类型(Enum Type)

更新记录
转载请注明出处:https://www.cnblogs.com/cqpanda/p/16690865.html
2022年9月16日 发布。
2022年9月10日 从笔记迁移到博客。

枚举类型(Enum Type)说明

枚举只有一种成员:命名的整型常量的集合

枚举是值类型

使用枚举有效地防止用户提供无效值,使代码更加清晰

定义枚举

image

注意:

​ 枚举成员不可以使用修饰符

​ 每个枚举成员底层都是一个常量值

​ 默认情况下,枚举成员的类型是int

​ 默认情况下,编译器把第一个成员赋值为0,后一个成员在前一个成员基础上加1

自定义枚举成员类型:
image

实例:定义enum类型底下的类型

public enum BorderSide : byte { Left, Right, Top, Bottom }

实例:定义enum类型每个值的具体数值

public enum BorderSide : byte { Left=1, Right=2, Top=10, Bottom=11 }

实例:定义enum类型,值来自其他enum类型

public enum HorizontalAlignment
{
    Left = BorderSide.Left,
    Right = BorderSide.Right,
    Center
}

实例:定义Enum类型,值来自自身

[Flags]
enum BorderSides
{
    None=0,
    Left=1, Right=1<<1, Top=1<<2, Bottom=1<<3,
    LeftRight = Left | Right,
    TopBottom = Top | Bottom,
    All = LeftRight | TopBottom
}

使用枚举

image

说明:枚举变量的内容本质是数值
image

带标志位的Enum类型(Flags Enums)

使用Flags特性修饰enum类型即可

说明:在一个数据单元上存储多个条件状态

实现:

使用[Flag]修饰枚举
image

各个成员值内存表示
image

一个枚举值拥有多个条件
image

使用时直接使用hasFlag方法判断即可
image

还可以判断多个条件
image

在新版本的C#中可以使用二进制字面量与位标志枚举结合使用

注意:使用Byte类型

[System.Flags]
public enum WondersOfTheAncientWorld: byte
{
    None = 0b_0000_0000, // i.e. 0
    GreatPyramidOfGiza = 0b_0000_0001, // i.e. 1
    HangingGardensOfBabylon = 0b_0000_0010, // i.e. 2
    StatueOfZeusAtOlympia = 0b_0000_0100, // i.e. 4
    TempleOfArtemisAtEphesus = 0b_0000_1000, // i.e. 8
    MausoleumAtHalicarnassus = 0b_0001_0000, // i.e. 16
    ColossusOfRhodes = 0b_0010_0000, // i.e. 32
    LighthouseOfAlexandria = 0b_0100_0000 // i.e. 64
}

实例:带标志位的Enum类型

[Flags]
enum BorderSides { None=0, Left=1, Right=2, Top=4, Bottom=8 }

实例:检测标志位是否存在

using System;
namespace ConsoleApp2
{
    /// <summary>
    /// 测试使用的Enum类型
    /// </summary>
    [Flags]
    public enum Direction
    {
        Top,
        Bottom,
        Left,
        Right,
    }

    class Program
    {
        static void Main(string[] args)
        {
            //多个值整合在一起
            Direction direction = Direction.Bottom & Direction.Right;
            //检测标志位
            if(direction.HasFlag(Direction.Bottom))
            {
                Console.WriteLine("Direction = Left+Top");
            }
            
            //wait
            Console.ReadKey();
        }
    }
}

枚举支持的运算符(Enum Operators)

= == != < > <= >= + - ^ & | ~

+= -= ++ -- sizeof

注意:

按位、算术和比较运算符返回处理基础整数值的结果

允许在枚举和集成类型之间进行加法运算,但不能在两个枚举之间进行加法运算

.NET中的枚举

.NET Enum类型中还可以使用一些有用的静态方法:

GetName方法以枚举类型对象和整数为参数,返回枚举成员名称

GetNames方法以枚举类型对象为参数,返回枚举中所有成员的名称

类型安全问题(Type-Safety Issues)

因为枚举可以在其基础整型类型之间进行转换

所以它的实际值可能超出合法枚举成员的界限

在实际的代码中需要为未知的枚举值做额外的处理 或者 检测值是否存在

实例:超出界限的转换

BorderSide b = (BorderSide) 12345;
Console.WriteLine (b); // 12345

实例:位运算和算数运算同样会导致问题

BorderSide b = BorderSide.Bottom;
b++; // No errors

实例:处理可能未知的枚举值

void Draw (BorderSide side)
{
    if (side == BorderSide.Left) {...}
    else if (side == BorderSide.Right) {...}
    else if (side == BorderSide.Top) {...}
    else {...} // Assume BorderSide.Bottom
}

实例:检测enum值是否存在

使用Enum.IsDefined静态方法

注意:Enum.IsDefined静态方法对Flags Enum不起作用

BorderSide side = (BorderSide) 12345;
Console.WriteLine (Enum.IsDefined (typeof (BorderSide), side)); // False

枚举转换(Enum Conversions)

枚举类型 与 数值类型转换

将枚举类型 与 整型类型转换 直接使用强制转换即可

实例:

using System;

namespace ConsoleApp1
{
    /// <summary>
    /// 定义测试使用的枚举类型
    /// </summary>
    enum Color { Red, Green, Pink, Blue }
    class Program
    {
        static void Main(string[] args)
        {
            //转为整数类型
            int i = (int)Color.Red;
            Console.WriteLine(i);   //0
            Color color = (Color)2;
            Console.WriteLine(color); //Pink

            //wait
            Console.ReadKey();
        }
    }
}

实例:枚举与数值类型转换

int i = (int) BorderSide.Left;
BorderSide side = (BorderSide) i;

实例:enum类型之间转换,本质是转为底层数值类型再进行准换

HorizontalAlignment h = (HorizontalAlignment) BorderSide.Right;
// same as:
HorizontalAlignment h = (HorizontalAlignment) (int) BorderSide.Right;

枚举类型 与 字符串类型转换

字符串转为Enum类型:使用Enum.Parse 或者Enum.TryParse

实例:使用Enum.Parse

using System;
namespace ConsoleApp1
{
    enum PandaOption
    {
        Option1,
        Option2,
        Option3
    }

    class Program
    {
        static void Main(string[] args)
        {
            string userInput = "Option1";

            PandaOption pandaOption;

            try
            {
                pandaOption = (PandaOption)Enum.Parse(typeof(PandaOption), userInput);
            }
            catch (ArgumentException e)
            {
                pandaOption = PandaOption.Option1;
            }

            Console.WriteLine(pandaOption);

            Console.ReadKey();
        }
    }
}

实例:使用Enum.TryParse

using System;
namespace ConsoleApp1
{
    /// <summary>
    /// 定义测试使用的枚举类型
    /// </summary>
    enum Color { Red, Green, Pink, Blue }
    class Program
    {
        static void Main(string[] args)
        {
            //转为字符串类型
            Console.WriteLine(Color.Red); //Red

            //转为枚举类型
            object result;
            Enum.TryParse(typeof(Color), "Blue", out result);
            if(result != null)
            {
                Console.WriteLine((Color)result); //Blue
            }

            //wait
            Console.ReadKey();
        }
    }
}

Enum类型自带静态方法

Enum类型转为字符串

string? name = Enum.GetName(typeof(Direction), 0);
Console.WriteLine(name);

获得Enum类型的所有元素的字符串

string[] names = Enum.GetNames(typeof(Direction));
foreach (var item in names)
{
    Console.WriteLine(item);
}

获得Enum类型的所有元素的数值

int[] values = (int[])Enum.GetValues(typeof(Direction));
foreach (var item in values)
{
    Console.WriteLine(item);
}

规范

必要时在枚举类型中定义一个表示空的成员 None = 0

在旧代码中为了兼容的考虑,不要删除枚举的旧成,确保代码的向后兼容性

避免使用枚举类型表示不完成类型的,比如版本号这种日后会进行修改的部分

避免创建保留给未来使用的枚举值,这样可以减少代码的BUG

避免枚举类型只包含一种单一的值

使用枚举替代布尔值

使用枚举值代替布尔值可以有效提高代码可读性

实例:

public enum LightSatus
{
    Unknow,
    On,
    Off,
}
public void LightDoing(LightSatus lightSatus)
{
    switch (lightSatus)
    {
        case LightSatus.Unknow:
            break;
        case LightSatus.On:
            break;
        case LightSatus.Off:
            break;
        default:
            break;
    }
}

Enum中静态方法

GetName可以获得枚举指定成员的字符串名称

GetNames可以获得枚举全部成员字符串组成的数组

实例:使用GetName 和 使用GetNames

using System;

namespace ConsoleApp3
{
enum Direction
{
    Up,
    Down,
    Left,
    Right
}
class Program
{
    static void Main(string[] args)
    {
        //获得指定值对应的字符串
        string v = Enum.GetName(typeof(Direction), 0);
        Console.WriteLine(v);

        //获得枚举类型中全部的的成员字符串
        string[] v2 = Enum.GetNames(typeof(Direction));
        foreach (string item in v2)
        {
            Console.WriteLine(item);
        }

        //wait
        Console.ReadKey();
    }
}
}
posted @ 2022-09-16 08:35  重庆熊猫  阅读(2588)  评论(0编辑  收藏  举报