zoukankan      html  css  js  c++  java
  • 深入浅出OOP(六): 理解C#的Enums

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

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

    image

    从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

    保留关键字

    image

      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)

    文章目录:

  • 相关阅读:
    LintCode Python 简单级题目 488.快乐数
    LintCode Python 简单级题目 100.删除排序数组中的重复数字 101.删除排序数组中的重复数字II
    LintCode Python 简单级题目 373.奇偶分割数组
    LintCode Python 简单级题目 39.恢复旋转排序数组
    LintCode Python 简单级题目 35.翻转链表
    LintCode Python 简单级题目 451.两两交换链表中的节点
    LintCode Python 简单级题目 174.删除链表中倒数第n个节点
    aws查看官方centos镜像imageid
    linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
    php配置优化-生产环境应用版
  • 原文地址:https://www.cnblogs.com/powertoolsteam/p/Diving-in-OOP-Day-Understanding-Enums-in-Csharp-A.html
Copyright © 2011-2022 走看看