利用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, iequatable {
static int counter = -1; //默认数值计数器
private static hashtable hashtable = new hashtable(); //不重复数值集合
protected static list members = new list(); //所有实例集合
private string name { get; set; }
private int value { get; set; }
/// /// 不指定数值构造实例
/// protected henum(string name)
{
this.name = name;
this.value = ++counter;
members.add(this);
if (!hashtable.containskey(this.value))
{
hashtable.add(this.value, this);
}
}
/// /// 指定数值构造实例
/// protected henum(string name, int value)
: this(name)
{
this.value = value;
counter = value;
}
/// /// 向string转换
/// /// public override string tostring()
{
return this.name.tostring();
}
/// /// 显式强制从int转换
/// /// /// public static explicit operator henum(int i)
{
if (hashtable.containskey(i))
{
return (henum)members[i];
}
return new henum(i.tostring(), i);
}
/// /// 显式强制向int转换
/// /// /// public static explicit operator int(henum e)
{
return e.value;
}
public static void foreach(action 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,
话说回来,此类还有诸多不足,充其量只能算是一个实验品,想要真正走向实用,还有些工作要做。在此发布,纪念此次实验及成果。


