Question

i have problem with enum

I need make a enum in base class or interface (but empty one)

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

and after make diffrent enums in some parent classes

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

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

and now i have next class with method when i have to use enum

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

It's there any way to do something like that ?

If not i have to use static ints in every 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<T>
{
   public void Foo(int enum)
   {
      int value = enum;
      // ...
   }
}

I't looks bad in code ... in some classes i have to use ~20+ variables

Was it helpful?

Solution

There is no such thing as an abstract enum (that can have different implementations in subclasses) - but generics may be an option:

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 };
}

The only problem is that this doesn't enforce that only enums are usable - you can do this at runtime, though - for example in a type initializer:

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

OTHER TIPS

It's amazing how often I find people arguing about why something is required, rather than answering the question asked or keeping schtum - either of which would be more helpful than wasting time questioning why a given enquiry has been made in preference to a different enquiry the respondent actually knows the answer to. Answering questions that have not been asked is in no way helpful, OK guys?!

Getting back to the topic at hand, I've hit exactly the above scenario this morning, and can understand why it would be useful to be able to define an Enum in an interface or base class, then re-define that same-named Enum in a class that derives from either the base or interface. One use for such a design is in object-relational mapping and control binding. You might have a set of Enums that describe which Properties of your derived classes are bindable to which types of Control, such as:

    public enum WebControlTextBoxProperties { }

    public enum WebControlLabelProperties { }

...and so on.

Since you don't know exactly which Properties will exist for a given derived class until the pertinent inheritance takes effect, but since you may also wish to have consistent Methods that consume the above Enums in your base or interface, it's a perfectly-valid design to expect to be able to define that the Enum will exist in the base/interface, but define exactly what members it has in a specific context in any derived classes.

I really wish this were possible in C# as it is in VB, because it'd be a really useful feature.

You should be able to declare an enum in a base class and then change the values per derived class i.e.

class MyClass
{
    public enum TestEnum { }

    public MyClass()
    {
    }
}

class MyDerivedClass
{
    public enum TestEnum { value1, value2, value3 }

    public MyDerivedClass()
    {
    }
}

MyDervied class would have access to TestEnum.value1, TestEnum.value2, TestEnum.value3, where as MyClass would only have access to the type.

However, personally I don't see the advantage of doing this I would declare ALL the values of the enum in the base class and only use the ones I need per class.

James.

No, it can't be done.

Note that many enums often indicate a problem with design (many switch constructs, for example). Check this link to see an example of how to refactor this: Replace conditional with polymorphism.

No, there is no way to enforce anything static in an interface.

Perhaps you need to rethink your design.

Why cant you define the enum in base class:

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

And use only the relevant members of enum in derived classes?

I am at work so cannot elaborate fully, but this is possible to a point. The downside to the code below is you cannot chain enums together, such as TextBoxProperties, and MyCustomTextBoxProperties : TextboxProperties

Here is the code.

    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; }
    }

YOU CAN ABSTRACT AN ENUM!

Why do people insist on claiming things are impossible without checking anything?

Sure, the .NET documentation is a little vague on this, but the System.Enum class, IS the abstraction of an enum. You can use System.Enum as a variable that will ONLY accept enumeration values, and you can access the name or value-type value of the enumeration through this class.

For example:

        // 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));

The output from the above code:

9

9

Blue

I like the accepted answer of @Marc Gravell. As i am a stackoverflow-newbie i am not allowed to comment. But i would like to add, that it is useful to also check the underlying Type of the enum - especially if you use the Flag Attribute and preform bit-wise flag-Testing operations...

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

Here's a solution that works for me:

in the parent class, declare the field as int, not as enum:

protected int state;

so the parent class can still use this value as an int, in order to provide serialization and deserializion of this value to disk.

Then, who overrides the class can do this:

enum states{
  state1, state2
}

this.state = state1.toInt();

and can access the actual value like this:

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

where toInt() is defined in a static class as follows:

public static class Utils
{

    public static int toInt(this state s)
    {
        return (int)s;
    }
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top