什么是最佳的“覆盖”枚举的方法?

18

可能是重复问题:
枚举类型“继承”

我有许多类继承自一个抽象类。抽象父类定义了一个带有一组值的枚举类型。其中一些子类继承了父类的枚举值,但是有些子类需要枚举值不同。是否有任何方法可以覆盖这些特定子类的枚举类型?如果没有,有什么好的方法可以实现我所描述的内容?

class ParentClass
{
    private MyEnum m_EnumVal;
    public virtual MyEnum EnumVal
    {
        get { return m_EnumVal; }
        set { m_EnumVal = value; }
    }

    public enum MyEnum { a, b, c };
}

class ChildClass : ParentClass
{
    private MyEnum m_EnumVal;
    public virtual MyEnum EnumVal
    {
        get { return m_EnumVal; }
        set { m_EnumVal = value; }
    }

    public enum MyEnum { d, e, f };
}

3
您可能对https://dev59.com/oHRA5IYBdhLWcg3w_DAw感兴趣。该问题涉及枚举继承。 - user568493
你不能覆盖枚举,而且C#不支持返回类型协变。你必须找到其他方法,这是不可能的。 - Cody Gray
@Cody Gray:我非常清楚这一点。我想知道的是最好的解决方案是什么。 - Tyler Treat
3个回答

22

如果你没有拥有或无法修改原始的基类或枚举,则其他答案是正确的。 如果可以,则可以使用类型安全的枚举模式。 它允许您定义自己的枚举类型,而不是从枚举派生,使其可以按照您的意愿执行任何操作(包括支持继承)。

public class MyEnum
{
  public static readonly MyEnum A = new MyEnum("A");
  public static readonly MyEnum B = new MyEnum("B");
  public static readonly MyEnum C = new MyEnum("C");

  public override string ToString()
  {
    return Value;
  }

  protected MyEnum(string value)
  {
    this.Value = value;
  }

  public string Value { get; private set; }
}

public sealed class MyDerivedEnum : MyEnum
{
  public static readonly MyDerivedEnum D = new MyDerivedEnum("D");

  private MyDerivedEnum(string value)
    : base(value)
  {
  }
}

class Program
{
    static void Main(string[] args)
    {
        MyEnum blah = MyEnum.A;
        System.Console.WriteLine(blah);
        blah = MyDerivedEnum.D;
        System.Console.WriteLine(blah);
    }
}

A
D
点击任意键继续. . .


现在我检查了一下,发现这跟另一个帖子里的答案几乎是一样的。我想这确实是一个重复的问题... - Merlyn Morgan-Graham
好的,我非常依赖于你的答案才能真正理解在另一页上给出的答案。我把所有三个代码集放在一起(感谢大屏幕!)并仔细研究了它。谢谢! 下一步:找出如何使“MyEnum”可枚举。 - Machtyn
救了我的一天,谢谢! - Adrian Frielinghaus
问题是,如果您拥有基类,为什么不直接添加所需的枚举? - LarryBud
1
@larrybud 当枚举完全满足您的所有需求,并且未来每个需要新枚举值的人都能够/被允许接触基础代码时,它就足够好用了。如果您需要添加其他抽象接口(例如,类型转换您的语言不支持的枚举),或者需要/想要遵循开放/封闭原则(Google开放/封闭原则。这里无法正确链接维基百科文章),那么使用类是最好的选择。 - Merlyn Morgan-Graham

6

类只允许你覆盖虚方法,而不是覆盖字段/内部类/枚举。你可以使用new关键字隐藏内部枚举,但是任何需要基类枚举的方法与子类枚举不兼容。

    class Base
    {
        public enum myEnum
        {
            hello, to, you
        }

        public void doIt(myEnum e)
        {
            Console.Out.WriteLine(e);
        }

        static void Main(string[] args)
        {
            Base a = new Child();
            a.doIt(Child.myEnum.hello); // this is a syntax error because doIt requires a Base.myEnum, not a Child.myEnum.
        }
    }

    class Child : Base
    {
        public new enum myEnum
        {
                hello, my, dear
        }
    }

你提到的不兼容问题是我正在面临的一个问题。我该如何避免这种情况? - Tyler Treat
使用枚举是不可能的。您可以创建自己的类,其中包含一堆预定义的常量值,然后扩展该类。但是,这不能删除基类中的任何值(根据如何执行重新定义应该没问题),只能添加到其中。请参见原始问题下面发布的bstn链接。 - helloworld922

1
你可以使用 "new" 关键字来覆盖在基类中定义的字段。
class Base
{
   public MyEnum A = MyEnum.Default;
}

class Derived : Base
{
   public new MyEnum A = MyEnum.Changed;
}

我使用了这个,它说它隐藏了继承成员。隐藏和覆盖之间有什么区别?为什么不能在枚举中使用 override 关键字? - Tyler Treat
virtualoverride 用于方法,而不是字段。 - Cheng Chen
问题是,我在类中还有一个字段用于存储枚举的值,所以我遇到了这个问题:'ChildClass.EnumValue':类型必须为 'ParentClass.MyEnum',以匹配被覆盖成员 'ParentClass.EnumValue' - Tyler Treat
@Tyler:请提供一些代码。 - Cheng Chen
也许你可以在基类中提供一个更隐蔽的枚举,包含所有可能的值,然后使用它来创建 Base.MyEnumnew Derived.MyEnum。虽然有些丑陋,但是... - Roberto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接