网站/小程序/APP个性化定制开发,二开,改版等服务,加扣:8582-36016

    工作中许多代码中用到枚举(enum),更用到了需要继承的枚举,由于C#的枚举不允许被继承,所以本文就来模拟实现一个可以继承的仿枚举吧

    工作中许多代码中用到枚举(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后面都是直接或间接为了“比较大小”要写的方法。

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

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


    评论 0

    暂无评论
    0
    0
    0
    立即
    投稿
    发表
    评论
    返回
    顶部