Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过继承扩展枚举_C#_Java_.net - Fatal编程技术网

C# 通过继承扩展枚举

C# 通过继承扩展枚举,c#,java,.net,C#,Java,.net,我知道这与enum的想法相反,但是有可能在C#/Java中扩展enum吗?我的意思是“扩展”,既可以向枚举添加新值,也可以从现有枚举继承OO 我认为这在Java中是不可能的,因为它只是最近才得到它们(Java5?)。不过,C#似乎更能原谅那些想做疯狂事情的人,所以我认为这可能是某种方式。想必它可以通过反射被破解(并不是说你真的会使用这种方法) 我不一定对实现任何给定的方法感兴趣,当我想到它时,它只是激起了我的好奇心:-)你不能从枚举继承/扩展,你可以使用它。如果您正在寻找一个整数值,它是内置的。

我知道这与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   );