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__是保留关键字。

枚举小结:

  1. enum表达了恒定的数值,枚举类型可以用字符串标示
  2. 无法声明char基础类型的枚举
  3. enum仅仅能继承自byte, sbyte, short, ushort, int, uint, long, 或ulong数据类型
  4. 默认的,enum是一个sealed类,既无法被继承
  5. enum类型隐式实现了System.Enum
  6. enum类型继承了3个接口:IComparable, IFormattable和IConvertible
  7. enum中,数字和字符串可以互相转换
  8. enum的值可被初始化为同样的值
  9. enum的值要在初始化时候确定
  10. enum中,'value__'关键字不能使用

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

文章目录:

深入浅出OOP(六): 理解C#的Enums的更多相关文章

  1. 网络编程懒人入门(六):深入浅出,全面理解HTTP协议

    本文引用了自简书作者“涤生_Woo”的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全称HyperText Transfer Protocol)是互联网上应用最为广 ...

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

    访问修饰符(或者叫访问控制符)是面向对象语言的特性之一,用于对类.类成员函数.类成员变量进行访问控制.同时,访问控制符也是语法保留关键字,用于封装组件. Public, Private, Protec ...

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

    本文是深入浅出OOP第二篇,主要说说继承的话题. 继承的介绍 在OOP中,继承有如下的定义: 继承是一种OOP的机制,用于派生继承预定义的类 在这个继承关系中,预定义的类是基类,新类是子类 继承常常用 ...

  4. JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[1]--(理解对象和对象属性类型)

    一.介绍 老铁们,这次是JS的面向对象的编程OOP(虽然我没有对象,心累啊,但是可以自己创建啊,哈哈). JS高程里第六章的内容,这章内容在我看来是JS中很难理解的一部分.所以分成三篇博客来逐个理清. ...

  5. JS--我发现,原来你是这样的JS:面向对象编程OOP[1]--(理解对象和对象属性类型)

    一.介绍 老铁们,这次是JS的面向对象的编程OOP(虽然我没有对象,心累啊,但是可以自己创建啊,哈哈). JS高程里第六章的内容,这章内容在我看来是JS中很难理解的一部分.所以分成三篇博客来逐个理清. ...

  6. iOS - 对OOA、OOD、OOP的理解

    很多人在求职的时候,会遇到一个这样的问题:“对OOD/OOP有较深的理解”,这个时候有人就会问OOD.OOP是什么呢?那么今天咱们就一块来看一下OOA.OOD.OOP到底是什么! (一)OOA--面向 ...

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

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  8. 我个人对OOP的理解

    OOP面向对象的思维:pay1:封装 A.避免使用非法数据赋值 B.保证数据的完整性 C.避免类内部发生修改的时候,导致整个程序的修改 pay2:继承 A.继承模拟了现实世界的关系,OOP中强调一切皆 ...

  9. C++——OOP面向对象理解

    从Rob Pike 的 Google+上的一个推看到了一篇叫<Understanding Object Oriented Programming>的文章,我先把这篇文章简述一下,然后再说说 ...

随机推荐

  1. make file

    CPPUTEST_USE_EXTENSIONS = Y如果没有这一句定义,CppUTestExt/MockSupport.h和CppUTestExt/MockSupport_c.h文件中的定义就不能用 ...

  2. 【软件工程】用map 实现把英语文本文件词和个数打印出来

    #include <iostream> #include <fstream> #include <string> #include <map> usin ...

  3. Ubuntu下shell脚本运行异常:bash和dash的区别

    Ubuntu下我用bash到语法写了一个shell脚本(准确的说是把书上的脚本敲进电脑),在ubuntu下,用sh test.sh来运行,但是出现了意料之外到结果,比如echo -e "\n ...

  4. Extjs学习笔记--Ext.tree.Panel

    Ext.create('Ext.tree.Panel', { title: 'Simple Tree', width: 200, height: 150, store: store, rootVisi ...

  5. POST 和GET传输的最大容量分别是多少?

    get 是通过URL提交数据,因此GET可提交的数据量就跟URL所能达到的最大长度有直接关系.很多文章都说GET方式提交的数据最多只能是1024字节,而 实际上,URL不存在参数上限的问题,HTTP协 ...

  6. 在ASP.NET中上传附件

    前台页面使用ASP控件:<asp:FileUpload ID="FileUpload" runat="server" Style="margin ...

  7. 《CSS3秘籍》(第三版)-读书笔记(2)

    第6章 文本格式化 1.  使用字体 字体font-family: 通用的字体样式: serif字体最适用于冗长的文字信息.这种字体使字母主笔画的结尾处会有一些细小的“足”. sans-serif字体 ...

  8. 理解GC日志

    每一种收集器的日志形式都是由它们自身的实现所决定的,换而言之,每个收集器的日志格式都可以不一样.但虚拟机设计者为了方便用户阅读,将各个收集器的日志都维持一定的共性,例如以下两段典型的GC日志: 33. ...

  9. 高频交易策略[z]

    Market Order以最高速下市价单(market order)是买方最基本的策略 Looking for Price Discrepancies 这个就是高频统计套利(high frequenc ...

  10. AngularJs自定义指令详解(1) - restrict

    下面所有例子都使用angular-1.3.16.下载地址:http://cdn.bootcss.com/angular.js/1.3.16/angular.min.js 既然AngularJs快要发布 ...