14

我对枚举有问题

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

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

在某些父类中进行不同的枚举之后

class Parent1
{
   public enum Test {A, B, C};
}

class Parent2
{
   public enum Test {J, H, K};
}

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

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

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

如果不是我必须在每个类中使用静态整数......

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<T>
{
   public void Foo(int enum)
   {
      int value = enum;
      // ...
   }
}

我的代码看起来不错......在某些类中我必须使用〜20多个变量

4

10 回答 10

28

令人惊讶的是,我经常发现人们争论为什么需要某些东西,而不是回答所提出的问题或保持 schtum - 这两者都比浪费时间质疑为什么要进行给定的调查而不是受访者的不同调查更有帮助居然知道答案。回答没有被问到的问题是没有任何帮助的,好吗?!

回到手头的话题,我今天早上正好遇到了上述情况,并且可以理解为什么能够在接口或基类中定义 Enum 会很有用,然后重新定义同名 Enum在从基类或接口派生的类中。这种设计的一种用途是对象关系映射和控件绑定。您可能有一组枚举来描述派生类的哪些属性可绑定到哪些类型的控件,例如:

    public enum WebControlTextBoxProperties { }

    public enum WebControlLabelProperties { }

...等等。

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

我真的希望这在 C# 中是可能的,就像在 VB 中一样,因为这将是一个非常有用的功能。

于 2010-10-19T08:39:15.790 回答
25

没有抽象枚举之类的东西(在子类中可以有不同的实现) - 但泛型可能是一种选择:

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

唯一的问题是,这并不强制只有枚举可用——不过,你可以在运行时执行此操作——例如在类型初始化器中:

static Base() {
    if (!typeof(T).IsEnum) throw new InvalidOperationException(
         typeof(T).Name + " is not an enum");
}
于 2009-06-23T09:56:32.677 回答
4

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

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 只能访问该类型。

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

詹姆士。

于 2009-06-23T09:59:40.893 回答
1

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

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

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

于 2009-06-23T09:57:18.200 回答
1

不,这做不到。

请注意,许多枚举通常表明设计存在问题(例如,许多开关构造)。查看此链接以查看如何重构此链接的示例:Replace conditional with polymorphism

于 2009-06-23T09:57:58.090 回答
0

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

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

于 2009-06-23T09:54:04.850 回答
0

我在工作,所以无法详细说明,但这在一定程度上是可能的。下面代码的缺点是不能将枚举链接在一起,例如 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; }
    }
于 2012-12-20T13:59:41.793 回答
0

可以抽象一个枚举!

为什么人们坚持声称事情是不可能的而不检查任何事情?

当然,.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

蓝色的

于 2013-05-24T00:45:28.810 回答
0

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

if ( !typeof(T).IsEnum || typeof(int) != Enum.GetUnderlyingType(typeof(T)) )
{
     throw new InvalidOperationException( typeof(T).Name + " is not an enum");
}
于 2017-05-13T19:22:33.393 回答
0

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

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

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;
    }
 }
于 2017-07-19T09:04:39.893 回答