利用C#实现可以继承的"枚举"

作者:BillySir 时间:2021-08-08 20:55:50 

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

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

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

此类要承担诸多功能:

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

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

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

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

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

using System;
using System.Collections;
using System.Collections.Generic;
  namespace HeritableEnum
  {
      public class HEnum : IComparable<HEnum>, IEquatable<HEnum>
      {
         static int counter = -1;            //默认数值计数器
        private static Hashtable hashTable = new Hashtable();       //不重复数值集合
        protected static List<HEnum> members = new List<HEnum>();   //所有实例集合
        private string Name { get; set; }
         private int Value { get; set; }
       /// <summary>
        /// 不指定数值构造实例
         /// </summary>
        protected HEnum(string name)
        {
            this.Name = name;
            this.Value = ++counter;
             members.Add(this);
            if (!hashTable.ContainsKey(this.Value))
             {
                hashTable.Add(this.Value, this);
             }
        }
         /// <summary>
        /// 指定数值构造实例
         /// </summary>
        protected HEnum(string name, int value)
            : this(name)
        {
            this.Value = value;
            counter = value;
         }
         /// <summary>
         /// 向string转换
         /// </summary>
         /// <returns></returns>
         public override string ToString()
        {
             return this.Name.ToString();
         }
        /// <summary>
         /// 显式强制从int转换
         /// </summary>
         /// <param name="i"></param>
         /// <returns></returns>
         public static explicit operator HEnum(int i)
         {
             if (hashTable.ContainsKey(i))
            {
                 return (HEnum)members[i];
            }
            return new HEnum(i.ToString(), i);
         }
         /// <summary>
        /// 显式强制向int转换
        /// </summary>
        /// <param name="e"></param>
         /// <returns></returns>
        public static explicit operator int(HEnum e)
        {
            return e.Value;
         }
        public static void ForEach(Action<HEnum> action)
        {
             foreach (HEnum item in members)
             {
                action(item);
            }
         }
         public int CompareTo(HEnum other)
         {
            return this.Value.CompareTo(other.Value);
        }
        public bool Equals(HEnum other)
         {
             return this.Value.Equals(other.Value);
         }
         public override bool Equals(object obj)
         {
           if (!(obj is HEnum))
                 return false;
             return this.Value == ((HEnum)obj).Value;
        }
       public override int GetHashCode()
        {
             HEnum std = (HEnum)hashTable[this.Value];
            if (std.Name == this.Name)
                return base.GetHashCode();
            return std.GetHashCode();
        }
        public static bool operator !=(HEnum e1, HEnum e2)
        {
            return e1.Value != e2.Value;
        }
        public static bool operator <(HEnum e1, HEnum e2)
        {
            return e1.Value < e2.Value;
        }
       public static bool operator <=(HEnum e1, HEnum e2)
        {
            return e1.Value <= e2.Value;
       }
        public static bool operator ==(HEnum e1, HEnum e2)
        {
            return e1.Value == e2.Value;
        }
        public static bool operator >(HEnum e1, HEnum e2)
        {
           return e1.Value > e2.Value;
        }
        public static bool operator >=(HEnum e1, HEnum e2)
        {
            return e1.Value >= e2.Value;
        }
    }
}

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

值得强调的是此类的所有构造方法必须是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,

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

来源:https://www.cnblogs.com/BillySir/archive/2012/02/15/2353395.html

标签:C#,枚举
0
投稿

猜你喜欢

  • IntelliJ IDEA优化配置的实现

    2023-01-01 03:29:55
  • Android仿淘宝物流信息TimeLineView

    2023-10-09 20:12:47
  • 区分Java中的ArrayList和LinkedList

    2021-05-26 11:09:55
  • Android自定义View之自定义评价打分控件RatingBar实现自定义星星大小和间距

    2023-03-14 04:30:16
  • Android实现中国象棋游戏(局域网版)

    2023-11-22 16:07:07
  • SpringBoot下如何实现支付宝接口的使用

    2023-11-06 14:26:15
  • idea springboot远程debug的操作方法

    2022-11-01 00:04:31
  • 在IDEA中安装MyBatis Log Plugin插件,执行mybatis的sql语句(推荐)

    2022-02-17 08:04:43
  • Android启动屏实现左右滑动切换查看功能

    2022-11-02 02:18:02
  • XListView实现下拉刷新和上拉加载原理解析

    2022-02-16 06:47:52
  • Java中的SuppressWarnings注解使用

    2023-08-18 17:31:19
  • C#Button窗体常用属性及事件详解

    2021-08-29 03:43:28
  • android长截屏原理及实现代码

    2021-11-13 05:55:50
  • kotlin 协程上下文异常处理详解

    2022-09-30 06:32:52
  • 教你使用java实现去除各种空格

    2022-09-21 21:27:07
  • android自定义控件实现简易时间轴(1)

    2022-09-24 00:42:23
  • JAVA设计模式之责任链模式详解

    2023-10-28 21:54:47
  • 提升java开发效率工具lombok使用争议

    2022-06-22 03:08:18
  • C#调用动态库

    2021-07-30 03:46:25
  • Java实现顺序栈原理解析

    2021-08-26 15:47:16
  • asp之家 软件编程 m.aspxhome.com