zoukankan      html  css  js  c++  java
  • 用C#制造可以继承的“枚举”

    工作中许多代码中用到枚举(enum),更用到了需要继承的枚举,由于C#的枚举不允许被继承(但允许继承自int/float等类型,这个不是我要的,在此不讨论)。

    我实现了一个可以继承的模拟枚举,在此与各位分享。
    于是我努力制造出可以继承的枚举,确切地说是可以继承的“仿枚举”。

    首先要仿System.Enum造一个仿它的地位的类,以“操控一切”。它也是一切可继承枚举的鼻祖。

    此类要承担诸多功能:

    1.与int/string之间的相互转换

    2.支持实例(静态属性)指定或不指定数值

    3.一些辅助的功能,如比较大小等

    4.一些方便使用的功能,如ForEach方法

    5.像string类(class)一样,表现出值传递的效果 

      1 using System;
      2 using System.Collections;
      3 using System.Collections.Generic;
      4 
      5 namespace HeritableEnum
      6 {
      7     public class HEnum : IComparable<HEnum>, IEquatable<HEnum>
      8     {
      9         static int counter = -1;            //默认数值计数器
     10         private static Hashtable hashTable = new Hashtable();       //不重复数值集合
     11         protected static List<HEnum> members = new List<HEnum>();   //所有实例集合
     12         private string Name { getset; }
     13         private int Value { getset; }
     14 
     15         /// <summary>
     16         /// 不指定数值构造实例
     17         /// </summary>
     18         protected HEnum(string name)
     19         {
     20             this.Name = name;
     21             this.Value = ++counter;
     22             members.Add(this);
     23             if (!hashTable.ContainsKey(this.Value))
     24             {
     25                 hashTable.Add(this.Value, this);
     26             }
     27         }
     28 
     29         /// <summary>
     30         /// 指定数值构造实例
     31         /// </summary>
     32         protected HEnum(string name, int value)
     33             : this(name)
     34         {
     35             this.Value = value;
     36             counter = value;
     37         }
     38 
     39         /// <summary>
     40         /// 向string转换
     41         /// </summary>
     42         /// <returns></returns>
     43         public override string ToString()
     44         {
     45             return this.Name.ToString();
     46         }
     47 
     48         /// <summary>
     49         /// 显式强制从int转换
     50         /// </summary>
     51         /// <param name="i"></param>
     52         /// <returns></returns>
     53         public static explicit operator HEnum(int i)
     54         {
     55             if (hashTable.ContainsKey(i))
     56             {
     57                 return (HEnum)members[i];
     58             }
     59             return new HEnum(i.ToString(), i);
     60         }
     61 
     62         /// <summary>
     63         /// 显式强制向int转换
     64         /// </summary>
     65         /// <param name="e"></param>
     66         /// <returns></returns>
     67         public static explicit operator int(HEnum e)
     68         {
     69             return e.Value;
     70         }
     71 
     72         public static void ForEach(Action<HEnum> action)
     73         {
     74             foreach (HEnum item in members)
     75             {
     76                 action(item);
     77             }
     78         }
     79 
     80         public int CompareTo(HEnum other)
     81         {
     82             return this.Value.CompareTo(other.Value);
     83         }
     84 
     85         public bool Equals(HEnum other)
     86         {
     87             return this.Value.Equals(other.Value);
     88         }
     89 
     90         public override bool Equals(object obj)
     91         {
     92             if (!(obj is HEnum))
     93                 return false;
     94             return this.Value == ((HEnum)obj).Value;
     95         }
     96 
     97         public override int GetHashCode()
     98         {
     99             HEnum std = (HEnum)hashTable[this.Value];
    100             if (std.Name == this.Name)
    101                 return base.GetHashCode();
    102             return std.GetHashCode();
    103         }
    104 
    105         public static bool operator !=(HEnum e1, HEnum e2)
    106         {
    107             return e1.Value != e2.Value;
    108         }
    109 
    110         public static bool operator <(HEnum e1, HEnum e2)
    111         {
    112             return e1.Value < e2.Value;
    113         }
    114 
    115         public static bool operator <=(HEnum e1, HEnum e2)
    116         {
    117             return e1.Value <= e2.Value;
    118         }
    119 
    120         public static bool operator ==(HEnum e1, HEnum e2)
    121         {
    122             return e1.Value == e2.Value;
    123         }
    124 
    125         public static bool operator >(HEnum e1, HEnum e2)
    126         {
    127             return e1.Value > e2.Value;
    128         }
    129 
    130         public static bool operator >=(HEnum e1, HEnum e2)
    131         {
    132             return e1.Value >= e2.Value;
    133         }
    134     }
    135 }

    经过时间跨度很长中的N次尝试后,写成了上面这个样子,实现了最基本的功能。ForEach后面都是直接或间接为了“比较大小”要写的方法。

    值得强调的是此类的所有构造方法必须是protected,以防止在类之外构造实例。它的子类也必须这样,以下是用于演示的子类:

    class EnumUse1 : HEnum
    {
        protected EnumUse1(string name) : base(name) { }

        protected EnumUse1(string name, int value) : base(name, value) { }

        public static EnumUse1 A = new EnumUse1("A");
        public static EnumUse1 B = new EnumUse1("B"2);
        public static EnumUse1 C = new EnumUse1("C"2);
        public static EnumUse1 D = new EnumUse1("D");
    }

    EnumUse1从HEnum继承,模拟以下的代码

    enum EnumUse1
    {
        A,
        B = 2,
        C = 2,
        D
    }

    再有一个子类从EnumUse1继承:

    class EnumUse2 : EnumUse1
    {
        protected EnumUse2(string name) : base(name) { }

        protected EnumUse2(string name, int value) : base(name, value) { }

        public static EnumUse2 E = new EnumUse2("E");
    }

    用起来跟系统原生的enum很像

    class Program
    {
        static void Main(string[] args)
        {
            bool b = EnumUse1.D >= EnumUse1.A;
            Console.WriteLine(b.ToString());
            Show(EnumUse2.E);
            HEnum.ForEach((x) => Console.WriteLine("{0} = {1},", x, (int)x));
        }

        static void Show(HEnum e)
        {
            Console.WriteLine(@"{0} = {1},""{2}""", e, (int)e, e.ToString());
        }
    }

    看,现在做到了可以比较大小,可以转化成string,(从string转回暂未做,但也不难),可以与int互转,值传递的效果(演示中无体现)。还比原生的enum多了ForEach功能,这点很方便。运行结果:

    True

    E = 4,"E"

    A = 0,

    B = 2,

    C = 2,

    D = 3,

    E = 4,

    话说回来,此类还有诸多不足,充其量只能算是一个实验品,想要真正走向实用,还有些工作要做。在此发布,纪念此次实验及成果。

  • 相关阅读:
    出现java.lang.UnsupportedClassVersionError 错误的原因
    java.lang.NoClassDefFoundError: javax/transaction/SystemException
    Hibernate参考文档学习笔记——Hibernate入门(二)
    图解Ant安装配置
    Hibernate参考文档学习笔记——Hibernate入门(一)
    scanf用在gets等函数之前会出现什么问题
    转向Web
    大道至简
    xdebug远程调试Vagrant虚拟机中web程序的注意点
    多个ssh private key的管理办法
  • 原文地址:https://www.cnblogs.com/BillySir/p/2353395.html
Copyright © 2011-2022 走看看