接口/基类中的C#枚举?

我有枚举的问题

我需要在基类或接口中创建一个枚举(但是空的)

class Base { public enum Test; // ??? } 

并在一些父类中创建不同的枚举之后

 class Parent1 { public enum Test {A, B, C}; } class Parent2 { public enum Test {J, H, K}; } 

现在,当我必须使用枚举时,我有下一节课的方法

 class Test { public void Foo(Test enum) { int value = (int) enum; // ... } } 

有没有办法做那样的事情?

如果不是我必须在每个class级使用静态内联…

 class Parent1 { public static int A = 0; public static int B = 5; public static int C = 7; } class Parent2 { public static int J = 1; public static int H = 3; public static int K = 6; } class Test { public void Foo(int enum) { int value = enum; // ... } } 

我在代码中看起来不好……在某些类中我必须使用~20 +变量

没有抽象枚举(在子类中可以有不同的实现) – 但generics可能是一个选项:

 class Base where T : struct { private T value; public void Foo(T value) { this.value = value; } } class Parent1 : Base { public enum Enum1 {A, B, C}; } class Parent2 : Base { public enum Enum2 { J, H, K }; } 

唯一的问题是,这并不强制只有枚举可用 – 您可以在运行时执行此操作 – 例如在类型初始值设定项中:

 static Base() { if (!typeof(T).IsEnum) throw new InvalidOperationException( typeof(T).Name + " is not an enum"); } 

令人惊讶的是,我经常发现人们争论为什么需要某些东西,而不是回答所提出的问题或保持问题 – 其中任何一个都比浪费时间质疑为什么特定的调查优先于受访者的不同调查更有帮助。实际上知道答案。 回答没有被问到的问题绝对没有帮助,伙计们好吗?!

回到手头的主题,我今天早上完全按照上面的场景,并且可以理解为什么能够在接口或基类中定义Enum,然后重新定义同名的Enum是有用的。在从基类或接口派生的类中。 这种设计的一个用途是对象关系映射和控制绑定。 您可能有一组枚举,用于描述派生类的哪些属性可绑定到哪些类型的Control,例如:

  public enum WebControlTextBoxProperties { } public enum WebControlLabelProperties { } 

…等等。

由于在相关inheritance生效之前,您不确切知道给定派生类将存在哪些属性,但由于您可能还希望在基础或接口中使用一致的方法来使用上述枚举,因此它是完全有效的设计期望能够定义Enum 将存在于基础/接口中,但确切地定义它在任何派生类中的特定上下文中具有哪些成员

我真的希望这在C#中是可行的,因为它在VB中,因为它是一个非常有用的function。

您应该能够在基类中声明枚举,然后更改每个派生类的值,即

 class MyClass { public enum TestEnum { } public MyClass() { } } class MyDerivedClass { public enum TestEnum { value1, value2, value3 } public MyDerivedClass() { } } 

MyDervied类可以访问TestEnum.value1,TestEnum.value2,TestEnum.value3,其中MyClass只能访问该类型。

但是,我个人并没有看到这样做的优点我会在基类中声明枚举的所有值,并且只使用每个类我需要的值。

詹姆士。

不,它无法完成。

请注意,许多枚举通常表明设计存在问题(例如,许多开关构造)。 检查此链接以查看如何重构此示例: 使用多态替换条件 。

不,没有办法在界面中强制执行任何静态操作。

也许你需要重新考虑你的设计。

为什么你不能在基类中定义枚举:

 class Base { public enum Test {A, B, C, J, H, K}; } 

并且在派生类中只使用枚举的相关成员?

我在工作,所以无法详细说明,但这有可能达到一定程度。 以下代码的缺点是您无法将枚举链接在一起,例如TextBoxProperties和MyCustomTextBoxProperties:TextboxProperties

这是代码。

  public enum Test { } public enum ThisTest { MyVal1, MyVal2, MyVal3 } public abstract class MyBase { public Test MyEnum { get; set; } } public class MyDerived : MyBase { public new ThisTest MyEnum { get; set; } } 

你可以抽象出一个枚举!

为什么人们坚持要求在没有检查的情况下做出事情是不可能的?

当然,.NET文档对此有点模糊,但System.Enum类是枚举的抽象。 您可以将System.Enum用作仅接受枚举值的变量,并且可以通过此类访问枚举的名称或值类型值。

例如:

  // abstracted enumeration value Enum abstractEnum = null; // set to the Console-Color enumeration value "Blue"; abstractEnum = System.ConsoleColor.Blue; // the defined value of "ConsoleColor.Blue" is "9": // you can get the value via the ToObject method: Console.WriteLine((int)Enum.ToObject(abstractEnum.GetType(), abstractEnum)); // or via the GetHashCode() method: Console.WriteLine(abstractEnum.GetHashCode()); // the name can also be acessed: Console.WriteLine(Enum.GetName(abstractEnum.GetType(), abstractEnum)); 

上面代码的输出:

9

9

蓝色

我喜欢@Marc Gravell的接受答案。 由于我是stackoverflow-newbie,我不被允许发表评论。 但我想补充一点,检查枚举的基础类型是有用的 – 特别是如果你使用Flag属性并执行逐位标记测试操作……

 if ( !typeof(T).IsEnum || typeof(int) != Enum.GetUnderlyingType(typeof(T)) ) { throw new InvalidOperationException( typeof(T).Name + " is not an enum"); } 

这是一个适合我的解决方案:

在父类中,将字段声明为int,而不是enum:

 protected int state; 

所以父类仍然可以将此值用作int,以便为磁盘提供此值的序列化和反序列化。

然后,谁覆盖该类可以这样做:

 enum states{ state1, state2 } this.state = state1.toInt(); 

并可以像这样访问实际值:

 ... if (this.state == states.state1.toInt()){ ... } else{ ... } 

其中toInt()在静态类中定义如下:

 public static class Utils { public static int toInt(this state s) { return (int)s; } }