MSDN定义:枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。 例如,假设您必须定义一个变量,该变量的值表示一周中的一天。

该变量只能存储七个有意义的值。 若要定义这些值,可以使用枚举类型。枚举类型是使用 enum 关键字声明的。

MSDN定义:枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。  例如,假设您必须定义一个变量,该变量的值表示一周中的一天。

该变量只能存储七个有意义的值。 若要定义这些值,可以使用枚举类型。枚举类型是使用 enum 关键字声明的。

 

从OOP上来说,枚举的角色和和class一样,它创建了一种新的数据类型。

1: namespace Enums

2: {

3: class Program

4: {

5: static void Main(string[] args)

6: {

7: }

8: }

9:

10: enum Color

11: {

12: Yellow,

13: Blue,

14: Brown,

15: Green

16: }

17: }

上面的代码,我们使用enum的关键字,创建了新的数据类型Color,并包含4个值:Yellow, Blue, Brown和Green。下面的例子我们给予Color枚举。

 

直接输出枚举,则可得到枚举的字符

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine(Color.Yellow);

9: Console.ReadLine();

10: }

11: }

12:

13: enum Color

14: {

15: Yellow,

16: Blue,

17: Brown,

18: Green

19: }

20: }

运行程序,输出:

Yellow

强转为int型,输出试试看:

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine((int)Color.Yellow);

9: Console.ReadLine();

10: }

11: }

12:

13: enum Color

14: {

15: Yellow,

16: Blue,

17: Brown,

18: Green

19: }

20: }

结果输出:

0

 

从上面的例子中,我们可以看到枚举的使用,如同static变量一样,可被直接使用。如不用转换则默认输出枚举定义的字符,强转后

则输出枚举对应的数字值---故枚举可表达恒量数值,或者命名的字符串标示。

 

基础数据类型

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine((byte)Color.Yellow);

9: Console.WriteLine((byte)Color.Blue);

10: Console.ReadLine();

11: }

12: }

13:

14: enum Color:byte

15: {

16: Yellow,

17: Blue,

18: Brown,

19: Green

20: }

21: }

 

结果输出为:

0

1

这里唯一做的修改是枚举Color继承自byte ,而不是默认的int型。

枚举可继承自数值型类型,如long, ulong, short, ushort, int, uint, byte 何sbyte。但是无法继承自char类型。

 

枚举可被枚举继承吗?

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine((byte)Color.Yellow);

9: Console.WriteLine((byte)Color.Blue);

10: Console.ReadLine();

11: }

12: }

13:

14: enum Color:byte

15: {

16: Yellow,

17: Blue,

18: Brown,

19: Green

20:

21: }

22:

23: enum Shades:Color

24: {

25:

26: }

27: }

编译,报错:

Type byte, sbyte, short, ushort, int, uint, long, or ulong expected.

枚举可被class继承吗?

1: enum Color:byte

2: {

3: Yellow,

4: Blue,

5: Brown,

6: Green

7: }

8:

9: class Derived:Color

10: {

11:

12: }

 

编译报错:

'Enums.Derived': cannot derive from sealed type 'Enums.Color'

 

接下来,我们看看枚举和这3个接口的关系:IComparable, IFormattable 和IConvertible。

A. IComparable

1: using System;

2:

3: namespace Enums

4: {

5: internal enum Color

6: {

7: Yellow,

8: Blue,

9: Green

10: }

11:

12: internal class Program

13: {

14: private static void Main(string[] args)

15: {

16: Console.WriteLine(Color.Yellow.CompareTo(Color.Blue));

17: Console.WriteLine(Color.Blue.CompareTo(Color.Green));

18: Console.WriteLine(Color.Blue.CompareTo(Color.Yellow));

19: Console.WriteLine(Color.Green.CompareTo(Color.Green));

20: Console.ReadLine();

21: }

22: }

23: }

结果输出:

-1

-1

1

0

-1表示小于关系,0表示等于关系,1表示大于关系。这里标明了enum默认继承了IComparable接口,故有CompareTo()函数。

B. IFormattable

1: using System;

2:

3: namespace Enums

4: {

5: internal enum Color

6: {

7: Yellow,

8: Blue,

9: Green

10: }

11:

12: internal class Program

13: {

14: private static void Main(string[] args)

15: {

16: System.Console.WriteLine(Color.Format(typeof(Color), Color.Green, "X"));

17: System.Console.WriteLine(Color.Format(typeof(Color), Color.Green, "d"));

18: Console.ReadLine();

19: }

20: }

21: }

结果输出:

00000002

2

Format方法继承自IFormatter 接口,它是一个static函数,因此可以被枚举Color直接使用。format需要传入3个参数,第一个是枚举的类型,

第二个参数是枚举值,第三个是格式化标示---二进制、十进制等。

C. IConvertible

1: Hide Copy Code

2: using System;

3:

4: namespace Enums

5: {

6: enum Color

7: {

8: Yellow,

9: Blue,

10: Green

11: }

12:

13: internal class Program

14: {

15: private static void Main(string[] args)

16: {

17: string[] names;

18: names = Color.GetNames(typeof (Color));

19: foreach (var name in names)

20: {

21: Console.WriteLine(name);

22: }

23: Console.ReadLine();

24: }

25: }

26: }

27:

结果输出:

Yellow

Blue

Green

GetNames函数是枚举Color的静态方法,用于获得枚举所有的字符标示名称集合。

同理也可使用ToString输出枚举的字符标示:

1: using System;

2:

3: namespace Enums

4: {

5: enum Color

6: {

7: Yellow,

8: Blue,

9: Green

10: }

11:

12: internal class Program

13: {

14: private static void Main(string[] args)

15: {

16: Console.WriteLine(Color.Blue.ToString());

17: Console.WriteLine(Color.Green.ToString());

18: Console.ReadLine();

19: }

20: }

21: }

 

显示输出:

Blue

Green

上面的例子显示,枚举可在int和string直接转换,这个特性是枚举使用中非常重要的一个功能。

 

试试看,枚举的字符标示是否可以重复定义:

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine((byte)Color.Yellow);

9: Console.WriteLine((byte)Color.Blue);

10: Console.ReadLine();

11: }

12: }

13:

14: enum Color

15: {

16: Yellow,

17: Blue,

18: Brown,

19: Green,

20: Blue

21: }

22: }

编译报错,结果:

Compile time error: The type 'Enums.Color' already contains a definition for 'Blue'

可见枚举中不能定义重复的字符标示。

 

再看另外一个例子:

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine((int)Color.Yellow);

9: Console.WriteLine((int)Color.Blue);

10: Console.WriteLine((int)Color.Brown);

11: Console.WriteLine((int)Color.Green);

12:

13: Console.ReadLine();

14: }

15: }

16:

17: enum Color

18: {

19: Yellow =2,

20: Blue,

21: Brown=9,

22: Green,

23:

24: }

25: }

结果:

2

3

9

10

 

 

从结果看,我们可以在枚举定义的时候重新指定数值,如我们指定了yellow为2,则Blue默认为Yellow+1,为3. 下来,我们指定了Brown为9,则

其下的Green为Brown + 1,为10。 这是一个有趣的enum特性。

 

如指定的数据类型超过枚举的定义类型,如何?

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8:

9: }

10: }

11:

12: enum Color:byte

13: {

14: Yellow =300 ,

15: Blue,

16: Brown=9,

17: Green,

18: }

19: }

编译报错:

Compile time error: Constant value '300' cannot be converted to a 'byte'

300超出了byte数据类型的范围,故报错。 枚举的类型检测非常好,在项目使用中很实用的功能。

 

枚举引用代码

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Console.WriteLine((int)Color.Yellow);

9: Console.WriteLine((int)Color.Blue);

10: Console.WriteLine((int)Color.Brown);

11: Console.WriteLine((int)Color.Green);

12:

13: Console.ReadLine();

14: }

15: }

16:

17: enum Color

18: {

19: Yellow = 2,

20: Blue,

21: Brown = 9,

22: Green = Yellow

23: }

24: }

结果输出:

2

3

9

2

这里,我们定义Green的值,引用了Color的Yellow枚举值。

枚举,是否可以在外面修改枚举值:

1: using System;

2: namespace Enums

3: {

4: class Program

5: {

6: static void Main(string[] args)

7: {

8: Color.Yellow = 3;

9: }

10: }

11:

12: enum Color

13: {

14: Yellow = 2,

15: Blue,

16: Brown = 9,

17: Green = Yellow

18: }

19: }

运行结果:

Compile time error: The left-hand side of an assignment must be a variable, property or indexer

编译报错了。可见枚举数值是常量,仅在初始化的时候确定,外部无法动态修改。

 

那么,枚举是否可以循环依赖?

1: using System;

2:

3: namespace Enums

4: {

5: internal enum Color

6: {

7: Yellow=Blue,

8: Blue

9: }

10:

11: internal class Program

12: {

13: private static void Main(string[] args)

14: {

15: }

16: }

17: }

编译结果:

Compile time error: The evaluation of the constant value for 'Enums.Color.Yellow' involves a circular definition

保留关键字

1: using System;

2:

3: namespace Enums

4: {

5: enum Color

6: {

7: value__

8: }

9:

10: internal class Program

11: {

12: private static void Main(string[] args)

13: {

14:

15: }

16: }

17: }

编译报错:

Compile time error: The enumerator name 'value__' is reserved and cannot be used

原因很简单,这里的value__是保留关键字。

枚举小结:

enum表达了恒定的数值,枚举类型可以用字符串标示

无法声明char基础类型的枚举

enum仅仅能继承自byte, sbyte, short, ushort, int, uint, long, 或ulong数据类型

默认的,enum是一个sealed类,既无法被继承

enum类型隐式实现了System.Enum

enum类型继承了3个接口:IComparable, IFormattable和IConvertible

enum中,数字和字符串可以互相转换

enum的值可被初始化为同样的值

enum的值要在初始化时候确定

enum中,'value__'关键字不能使用

 

原文:Diving in OOP (Day 6): Understanding Enums in C# (A Practical Approach)

 

文章目录:

深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)

深入浅出OOP(二): 多态和继承(继承)

深入浅出OOP(三): 多态和继承(动态绑定/运行时多态)

深入浅出OOP(四): 多态和继承(抽象类)

深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Internal/Sealed/Constants)

深入浅出OOP(六): 理解C#的Enums

查看原文