C# 通过继承扩展枚举
我知道这与enum的想法相反,但是有可能在C#/Java中扩展enum吗?我的意思是“扩展”,既可以向枚举添加新值,也可以从现有枚举继承OO 我认为这在Java中是不可能的,因为它只是最近才得到它们(Java5?)。不过,C#似乎更能原谅那些想做疯狂事情的人,所以我认为这可能是某种方式。想必它可以通过反射被破解(并不是说你真的会使用这种方法)C# 通过继承扩展枚举,c#,java,.net,C#,Java,.net,我知道这与enum的想法相反,但是有可能在C#/Java中扩展enum吗?我的意思是“扩展”,既可以向枚举添加新值,也可以从现有枚举继承OO 我认为这在Java中是不可能的,因为它只是最近才得到它们(Java5?)。不过,C#似乎更能原谅那些想做疯狂事情的人,所以我认为这可能是某种方式。想必它可以通过反射被破解(并不是说你真的会使用这种方法) 我不一定对实现任何给定的方法感兴趣,当我想到它时,它只是激起了我的好奇心:-)你不能从枚举继承/扩展,你可以使用它。如果您正在寻找一个整数值,它是内置的。
我不一定对实现任何给定的方法感兴趣,当我想到它时,它只是激起了我的好奇心:-)你不能从枚举继承/扩展,你可以使用它。如果您正在寻找一个整数值,它是内置的。Hmmm-据我所知,这是不可能做到的-枚举是在设计时编写的,用于方便程序员
我敢肯定,在编译代码时,枚举中的名称将替换为等价的值,从而删除枚举的概念,并(因此)扩展它的能力。如果返回源代码并以任何其他方式进行编辑,添加枚举是一件相当常见的事情(继承或反射,如果可能的话)很可能在您升级库时返回并击中您,并且他们引入了相同的枚举名称或相同的枚举值-我见过很多低级别代码,其中整数与二进制编码匹配,您会遇到问题
理想情况下,引用枚举的代码应该只写为equals(或switches),并且尽量不希望枚举集为const,以防将来发生错误。您可以在运行时使用.NET反射从现有枚举中检索标签和值(
enum.GetNames()
和enum.GetValues()
是您将使用的两种特定方法),然后使用代码注入创建一个包含这些元素和一些新元素的新元素。这似乎与“从现有枚举继承”有些矛盾。无法扩展枚举的原因是,它会导致多态性问题
假设您有一个具有值A、B和C的枚举MyEnum,并使用值D将其扩展为MyExtEnum
假设一个方法在某个地方需要一个myEnum值,例如作为一个参数。提供一个MyExtEnum值应该是合法的,因为它是一个子类型,但是现在当发现该值是D时,您将怎么做
若要消除此问题,扩展枚举是非法的当内置枚举不足时,您可以使用旧的方式并自行设计。例如,如果您想添加其他属性,例如描述字段,您可以按如下方式执行:
public class Action {
public string Name {get; private set;}
public string Description {get; private set;}
private Action(string name, string description) {
Name = name;
Description = description;
}
public static Action DoIt = new Action("Do it", "This does things");
public static Action StopIt = new Action("Stop It", "This stops things");
}
然后,您可以将其视为枚举,如下所示:
public void ProcessAction(Action a) {
Console.WriteLine("Performing action: " + a.Name)
if (a == Action.DoIt) {
// ... and so on
}
}
诀窍是确保构造函数是私有的(或者如果你想继承的话是受保护的),并且你的实例是静态的。如果你指的是基类意义上的扩展,那么在Java中……不 但是,如果这是您的意思,您可以扩展枚举值,使其具有属性和方法 例如,以下使用括号枚举:
class Person {
enum Bracket {
Low(0, 12000),
Middle(12000, 60000),
Upper(60000, 100000);
private final int low;
private final int high;
Brackets(int low, int high) {
this.low = low;
this.high = high;
}
public int getLow() {
return low;
}
public int getHigh() {
return high;
}
public boolean isWithin(int value) {
return value >= low && value <= high;
}
public String toString() {
return "Bracket " + low + " to " + high;
}
}
private Bracket bracket;
private String name;
public Person(String name, Bracket bracket) {
this.bracket = bracket;
this.name = name;
}
public String toString() {
return name + " in " + bracket;
}
}
班级人员{
枚举括号{
低(0,12000),
中等(1200060000),
上限(60000,100000);
私人最终int低;
私家车总分偏高;
括号(整数低位,整数高位){
这个.低=低;
这个高=高;
}
公共int getLow(){
低回报;
}
公共int getHigh(){
高回报;
}
公共布尔值isWithin(int值){
返回值>=low&&value枚举应该表示所有可能值的枚举,因此扩展反而不符合这个想法
但是,在Java(可能是C++0x)中可以做的是使用接口而不是枚举类。然后将标准值放入实现该功能的枚举中。显然,您不能使用Java.util.EnumSet等。这是“更多NIO功能”中采用的方法,应该在JDK7中
public interface Result {
String name();
String toString();
}
public enum StandardResults implements Result {
TRUE, FALSE
}
public enum WTFResults implements Result {
FILE_NOT_FOUND
}
不久前看到一篇关于Java的帖子,请查看。您走错了路:枚举的子类的条目会更少
在伪代码中,思考:
enum Animal { Mosquito, Dog, Cat };
enum Mammal : Animal { Dog, Cat }; // (not valid C#)
任何能够接受动物的方法都应该能够接受哺乳动物,但反过来就不行了。子类化是为了使某些东西更具体,而不是更一般。这就是为什么“对象”类层次结构的根。同样,如果枚举是可继承的,则枚举层次结构的假设根将具有所有可能的符号
但是不,C#/Java不允许子枚举,AFAICT,尽管它有时会非常有用。这可能是因为他们选择将枚举实现为int(如C)而不是interned符号(如Lisp)。(上面,(动物)1表示什么,(哺乳动物)1表示什么,它们的值相同吗?)
您可以编写自己的类似枚举的类(使用不同的名称)不过,这就提供了这一点。使用C#attributes时,它甚至看起来有点不错。我没有看到其他人提到这一点,但枚举的序数值很重要。例如,使用grails时,当您将枚举保存到数据库时,它使用序数值。如果您可以以某种方式扩展枚举,扩展的序数值是多少离子?如果你把它扩展到多个地方,你怎么能保持这些序数的某种秩序?序数值的混乱/不稳定将是一件坏事,这可能是语言设计者没有触及这一点的另一个原因
另一个困难是,如果您是语言设计师,如何保留values()方法的功能,该方法应返回所有枚举值。您将在上调用该方法,并如何收集所有值?我希望能够
my_ctrl.Anchor = AnchorStyles.Right | AnchorStyles.Bottom;
my_ctrl.Anchor = AnchorStyles.BottomRight;
enum Person (JOHN SAM}
enum Student extends Person {HARVEY ROSS}
Person person = Student.ROSS; //not legal
public enum MyEnum { A = 1, B = 2, C = 4 }
public const MyEnum D = (MyEnum)(8);
public const MyEnum E = (MyEnum)(16);
func1{
MyEnum EnumValue = D;
switch (EnumValue){
case D: break;
case E: break;
case MyEnum.A: break;
case MyEnum.B: break;
}
}
enum Animals { Dog, Cat }
enum AnimalsExt { Dog = Animals.Dog, Cat= Animals.Cat, MyOther}
// BUT CAST THEM when using:
var xyz = AnimalsExt.Cat;
MethodThatNeedsAnimal( (Animals)xyz );