C# 通过继承扩展枚举
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/55375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extending an enum via inheritance
提问by alastairs
I know this rather goes against the idea of enums, but is it possible to extend enums in C#/Java? I mean "extend" in both the sense of adding new values to an enum, but also in the OO sense of inheriting from an existing enum.
我知道这与枚举的想法背道而驰,但是是否可以在 C#/Java 中扩展枚举?我的意思是“扩展”既是向枚举添加新值的意义上,也是从现有枚举继承的面向对象意义上的“扩展”。
I assume it's not possible in Java, as it only got them fairly recently (Java 5?). C# seems more forgiving of people that want to do crazy things, though, so I thought it might be possible some way. Presumably it could be hacked up via reflection (not that you'd every actually use that method)?
我认为这在 Java 中是不可能的,因为它最近才得到它们(Java 5?)。不过,C# 似乎更宽容那些想做疯狂事情的人,所以我认为这可能以某种方式成为可能。大概它可以通过反射来破解(不是说你每个人都会实际使用这种方法)?
I'm not necessarily interested in implementing any given method, it just provoked my curiosity when it occurred to me :-)
我不一定对实现任何给定的方法感兴趣,它只是在我想到时激起了我的好奇心:-)
采纳答案by Rik
The reason you can't extend Enums is because it would lead to problems with polymorphism.
不能扩展 Enums 的原因是它会导致多态性问题。
Say you have an enum MyEnum with values A, B, and C , and extend it with value D as MyExtEnum.
假设您有一个值为 A、B 和 C 的枚举 MyEnum,并将其扩展为值为 D 作为 MyExtEnum。
Suppose a method expects a myEnum value somewhere, for instance as a parameter. It should be legal to supply a MyExtEnum value, because it's a subtype, but now what are you going to do when it turns out the value is D?
假设一个方法在某处需要一个 myEnum 值,例如作为参数。提供 MyExtEnum 值应该是合法的,因为它是一个子类型,但是现在当结果是 D 时你要做什么?
To eliminate this problem, extending enums is illegal
为了消除这个问题,扩展枚举是非法的
回答by bdukes
You can't inherit from/extend an enum, you can use attributesto declare a description. If you're looking for an integer value, that's built-in.
您不能继承/扩展枚举,您可以使用属性来声明 description。如果您正在寻找一个整数值,那是内置的。
回答by Chris Roberts
Hmmm - as far as I know, this can't be done - enumerations are written at design-time and are used as a convenience to the programmer.
嗯 - 据我所知,这是不可能的 - 枚举是在设计时编写的,用于方便程序员。
I'm pretty sure that when the code is compiled, the equivalent values will be substituted for the names in your enumeration, thereby removing the concept of an enumeration and (therefore) the ability to extend it.
我很确定在编译代码时,等效值将替换枚举中的名称,从而消除枚举的概念和(因此)扩展它的能力。
回答by Oskar
Adding enums is a fairly common thing to do if you go back to the source code and edit, any other way (inheritance or reflection, if either is possible) is likely to come back and hit you when you get an upgrade of the library and they have introduced the same enum name orthe same enum value - I have seen plenty of lowlevel code where the integer number matches to the binary encoding, where you would run into problems
如果您返回源代码并进行编辑,则添加枚举是一件相当常见的事情,任何其他方式(继承或反射,如果可能的话)都可能在您升级库和他们引入了相同的枚举名称或相同的枚举值——我见过很多低级代码,其中整数与二进制编码相匹配,在那里你会遇到问题
Ideally code referencing enums should be written as equals only (or switches), and try to be future proof by not expecting the enum set to be const
理想情况下,引用枚举的代码应该只写为 equals(或开关),并尝试通过不期望枚举集为 const 来证明未来
回答by McKenzieG1
You can use .NET reflection to retrieve the labels and values from an existing enum at run-time (Enum.GetNames()
and Enum.GetValues()
are the two specific methods you would use) and then use code injection to create a new one with those elements plus some new ones. This seems somewhat analagous to "inheriting from an existing enum".
您可以使用.NET反射在运行时检索从现有的枚举的标签和值(Enum.GetNames()
和Enum.GetValues()
你会使用这两种具体方法),然后使用代码注入来创建一个新的与这些元素加上一些新的问题。这似乎有点类似于“从现有枚举继承”。
回答by tsimon
When built-in enums aren't enough, you can do it the old fashion way and craft your own. For example, if you wanted to add an additional property, for example, a description field, you could do it as follows:
当内置枚举不够用时,您可以按照旧时尚的方式来制作自己的枚举。例如,如果您想添加一个额外的属性,例如一个描述字段,您可以按如下方式进行:
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");
}
You can then treat it like an enum like so:
然后,您可以将其视为枚举,如下所示:
public void ProcessAction(Action a) {
Console.WriteLine("Performing action: " + a.Name)
if (a == Action.DoIt) {
// ... and so on
}
}
The trick is to make sure that the constructor is private (or protected if you want to inherit), and that your instances are static.
诀窍是确保构造函数是私有的(或者如果您想继承则受保护),并且您的实例是静态的。
回答by Allain Lalonde
If you mean extends in the Base class sense, then in Java... no.
如果您的意思是在 Base 类意义上扩展,那么在 Java 中......不。
But you can extend an enum value to have properties and methods if that's what you mean.
但是,如果这就是您的意思,您可以扩展枚举值以具有属性和方法。
For example, the following uses a Bracket enum:
例如,以下使用 Bracket 枚举:
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;
}
}
回答by Tom Hawtin - tackline
Enums are supposed to represent the enumeration of all possible values, so extending rather does go against the idea.
枚举应该代表所有可能值的枚举,因此扩展而不是与这个想法背道而驰。
However, what you can do in Java (and presumably C++0x) is have an interface instead of a enum class. Then put you standard values in an enum that implements the feature. Obviously you don't get to use java.util.EnumSet and the like. This is the approach taken in "more NIO features", which should be in JDK7.
但是,您可以在 Java(大概是 C++0x)中做的是有一个接口而不是枚举类。然后将标准值放入实现该功能的枚举中。显然你不能使用 java.util.EnumSet 等。这是“more NIO features”中采用的方法,JDK7中应该有。
public interface Result {
String name();
String toString();
}
public enum StandardResults implements Result {
TRUE, FALSE
}
public enum WTFResults implements Result {
FILE_NOT_FOUND
}
回答by jwiklund
Saw a post regarding this for Java a while back, check out http://www.javaspecialists.eu/archive/Issue161.html.
不久前看到一篇关于 Java 的帖子,请查看http://www.javaspecialists.eu/archive/Issue161.html。
回答by Ken
You're going the wrong way: a subclass of an enum would have fewerentries.
你走错了路:枚举的子类会有更少的条目。
In pseudocode, think:
在伪代码中,思考:
enum Animal { Mosquito, Dog, Cat };
enum Mammal : Animal { Dog, Cat }; // (not valid C#)
Any method that can accept an Animal should be able to accept a Mammal, but not the other way around. Subclassing is for making something more specific, not more general. That's why "object" is the root of the class hierarchy. Likewise, if enums were inheritable, then a hypothetical root of the enum hierarchy would have every possible symbol.
任何可以接受 Animal 的方法都应该能够接受 Mammal,但反过来不行。子类化是为了使某些东西更具体,而不是更一般。这就是为什么“对象”是类层次结构的根。同样,如果枚举是可继承的,那么枚举层次结构的假设根将具有所有可能的符号。
But no, C#/Java don't allow sub-enums, AFAICT, though it would be really useful at times. It's probably because they chose to implement Enums as ints (like C) instead of interned symbols (like Lisp). (Above, what does (Animal)1 represent, and what does (Mammal)1 represent, and are they the same value?)
但是不,C#/Java 不允许子枚举,AFAICT,尽管它有时真的很有用。这可能是因为他们选择将枚举实现为整数(如 C)而不是内部符号(如 Lisp)。(上边(Animal)1代表什么,(Mammal)1代表什么,它们是同一个值吗?)
You could write your own enum-like class (with a different name) that provided this, though. With C# attributes it might even look kind of nice.
不过,您可以编写自己的类似枚举的类(使用不同的名称)来提供此功能。使用 C# 属性,它甚至可能看起来不错。