关于enum的那些事儿

时间:2021-08-10 19:42:30

自从当年明月的《明朝的那些事儿》爆红之后,以***那些事儿命名的文章便层出不穷。个人认为,这样的命名通俗但具有吸引力,容易接地气。哈哈,所以我也写了几篇以《***那些事儿》的文章。当然这篇文章也是为了保持队形,勿怪,看内容。

先此声明下,本文章中有转载其他博友的文章,另有些网络资源。为尊重原创者,在文章末尾,会给出链接。

C#中的enum

在C#的官方文档中给出这样的解释:

enum 关键字用于声明枚举,即一种由一组称为枚举数列表的命名常量组成的独特类型。

通常情况下,最好是在命名空间内直接定义枚举,以便该命名空间中的所有类都能够同样方便地访问它。但是,还可以将枚举嵌套在类或结构中。默认情况下,第一个枚举数的值为 0,后面每个枚举数的值依次递增 1。例如,下面的枚举,Sat 是 0,Sun 是 1,Mon 是 2 等.

enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};

如下面的示例所示枚举数可用初始值来重写默认值。

enum Days {Sat=, Sun, Mon, Tue, Wed, Thu, Fri};

在此枚举中,强制元素序列从 1 而不是 0 开始。但是,一般建议包括值为 0 的常量。

每种枚举类型都有基础类型,该类型可以是除 char 以外的任何整型。枚举元素的默认基础类型为 int。要声明另一整型枚举(如 byte),请在标识符之后紧跟类型,然后再使用冒号,如下面的示例所示。

enum Days : byte {Sat=, Sun, Mon, Tue, Wed, Thu, Fri};

准许使用的枚举类型有 byte、sbyte、short、ushort、int、uint、long 或 ulong。

可以给Days类型的变量赋以基础类型范围内的任何值,所赋的值不限于已命名的常数。

enum E的默认值为表达式(E)0生成的值。

基础类型指定为每个枚举数分配的存储大小。但是,从 enum 类型到整型的转换需要用显式类型转换来完成。例如,下面的语句使用强制转换(从enum 转换为 int)将枚举数 Sun 赋值给一个 int 类型的变量。

int x = (int)Days.Sun;

枚举类型作为位标志

可以使用枚举类型定义位标志,从而使该枚举类型的实例可以存储枚举数列表中定义的值的任意组合。

创建位标志枚举的方法是应用 System.FlagsAttribute 特性并适当定义一些值,以便可以对这些值执行 ANDORNOT 和 XOR 按位运算。 在位标志枚举中包含一个值为零(表示“未设置任何标志”)的命名常量。如果零值不表示“未设置任何标志”,则请不要为标志指定零值。

在下面的示例中,定义了 Days 枚举的另一个版本,命名为 Days2。 Days2 具有 Flags 特性,且它的每个值都是 2 的若干次幂,指数依次递增。 这样,您将能够创建值为 Days2.Tuesday 和 Days2.Thursday 的 Days2 变量。

enum Days2
{
None = 0x0,
Sunday = 0x1,
Monday = 0x2,
Tuesday = 0x4,
Wednesday = 0x8,
Thursday = 0x10,
Friday = 0x20,
Saturday = 0x40
}
class MyClass
{
Days2 meetingDays = Days2.Tuesday | Days2.Thursday;
}

若要在某个枚举上设置标志,请使用按位OR运算符,如下面的示例所示:

// Initialize with two flags using bitwise OR.
meetingDays = Days2.Tuesday | Days2.Thursday; // Set an additional flag using bitwise OR.
meetingDays = meetingDays | Days2.Friday; Console.WriteLine("Meeting days are {0}", meetingDays);
// Output: Meeting days are Tuesday, Thursday, Friday // Remove a flag using bitwise XOR.
meetingDays = meetingDays ^ Days2.Tuesday;
Console.WriteLine("Meeting days are {0}", meetingDays);
// Output: Meeting days are Thursday, Friday

若要确定了是否设置了特定标志,请使用按位AND运算,如下面的示例所示:

// Test value of flags using bitwise AND.
bool test = (meetingDays & Days2.Thursday) == Days2.Thursday;
Console.WriteLine("Thursday {0} a meeting day.", test == true ? "is" : "is not");
// Output: Thursday is a meeting day.

C#语言使用示例

enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
enum Months : byte { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }; Days today = Days.Monday;
int dayNumber =(int)today;
Console.WriteLine("{0} is day number #{1}.", today, dayNumber); Months thisMonth = Months.Dec;
byte monthNumber = (byte)thisMonth;
Console.WriteLine("{0} is month number #{1}.", thisMonth, monthNumber);

输出:

Monday is day number #1.
Dec is month number #11.

C++使用示例

enum  DAY
{
saturday,
sunday = ,
monday,
tuesday,
wednesday,
thursday,
firday
}workday; enum FRUIT
{
apple,
orange,
banana,
pea
};
int main()
{
int ret = saturday;
workday = (DAY)pea;
cout << workday << endl;
cout << ret << endl;
getchar();
return ;
}

不同枚举定义的类型元素,要进行相互赋值,必须进行强制类型转换。在DAY中,saturday的值为0。因为saturday后面有sunday=0,枚举值最小为0。但是enum类型的枚举值向int的转化是隐式进行的,无须强制转换。

C++中的enum

相对于C#中的enum,C++的enum有3个缺陷:

  • 不支持组合特性,即FlagAttribute属性。
  • 不支持toString方法,转换为字符串需要特别的函数实现。
  • 不支持命名空间的特性。
  • 在C++中,使用枚举类型不必带有类型限定名,直接使用,类似于使用宏。这样如果在同一个文件中出现两个枚举类型定义了相同名称的枚举值,则编译失败。

例如:在上面的文件中:enum FOOD{rice,apple};会出现编译错误,因为FOOD中的apple和FRUIT里面的apple重名,会有歧义。

枚举类型使用的规定

1)枚举值是常量,不是变量,所以不能在程序中用赋值语句对其赋值。

例如:

saturday = 1;//error

sunday = 4;//error

monday = thursday;//error

2)枚举元素本身由系统定义了一个表示序号的数值,默认从0开始定义。例如在FRUIT中:

cout<<apple<<orange<<banana<<pea;

其输出值为:0123。

3)只能把用一类型的枚举值赋给枚举变量,不能把元素的值直接赋给枚举变量。

例如在程序中:

workday = saturday;

workday = (DAY)apple;//强制类型转换,从FRUIT转换为DAY

参考链接

https://msdn.microsoft.com/zh-cn/library/sbbt4032.aspx

https://msdn.microsoft.com/zh-cn/library/cc138362.aspx