tags:

views:

7608

answers:

8
+15  Q: 

Enum "Inheritance"

I have an enum in a low level namespace. I'd like to provide a class or enum in a mid level namespace that "inherits" the low level enum.

namespace low
{
   public enum base
   {
      x, y, z
   }
}

namespace mid
{
   public enum consume : low.base
   {
   }
}

I'm hoping that this is possible, or perhaps some kind of class that can take the place of the enum consume which will provide a layer of abstraction for the enum, but still let an instance of that class access the enum.

Thoughts?

EDIT: One of the reasons I haven't just switched this to consts in classes is that the low level enum is needed by a service that I must consume. I have been given the WSDLs and the XSDs, which define the structure as an enum. The service cannot be changed.

+7  A: 

The short answer is no. You can play a bit, if you want:

You can always do something like this:

private enum Base
{
    A,
    B,
    C
}

private enum Consume
{
    A = Base.A,
    B = Base.B,
    C = Base.C,
    D,
    E
}

But, it doesn't work all that great because Base.A != Consume.A

You can always do something like this, though:

public static class Extensions
{
    public static T As<T>(this Consume c) where T : struct
    {
        return System.Enum.Parse(typeof(T), c.ToString(), false);
    }
}

In order to cross between Base and Consume...

You could also cast the values of the enums as ints, and compare them as ints instead of enum, but that kind of sucks too.

Brian Genisio
A: 

Enums are not actual classes, even if they look like it. Internally, they are treated just like their underlying type (by default Int32). Therefore, you can only do this by "copying" single values from one enum to another and casting them to their integer number to compare them for equality.

Lucero
+1  A: 

Ignoring the fact that base is a reserved word you cannot do inheritance of enum.

The best thing you could do is something like that:

public enum Baseenum
{
   x, y, z
}

public enum Consume
{
   x = Baseenum.x,
   y = Baseenum.y,
   z = Baseenum.z
}

public void Test()
{
   Baseenum a = Baseenum.x;
   Consume newA = (Consume) a;

   if ((Int32) a == (Int32) newA)
   {
   MessageBox.Show(newA.ToString());
   }
}

Since they're all the same base type (ie: int) you could assign the value from an instance of one type to the other which a cast. Not ideal but it work.

Pascal
base is reserved but Base isn't
erikkallen
He's referring to the OP's use of base as the enum name, it's just an example name I'm sure
John Rasch
+23  A: 

This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.

See section 8.5.2 of the CLI spec for the full details. Relevant information from the spec

  • All enums must derive from System.Enum
  • Because of the above, all enums are value types and hence sealed
JaredPar
+1 for spec reference.
Cumbayah
A: 

Enums cannot be derrived from other enums, but only from int, uint, short, ushort, long, ulong, byte and sbyte.

Like Pascal said, you can use other enum's values or constants to initialize an enum value, but that's about it.

Jeroen Landheer
It's a bit of a misnomer because of the c# syntax but enum's cannot actually inherit from int,uint,etc ... Under the hood they still inherit from System.Enum. It's just that the member representing the enum is typed to the int,uint, etc ...
JaredPar
@JaredPar. When an enum is derrived from an uint, it means it's values are all uint, etc. By default an enum inherits int. (Take a look at the C# specification, enum SomeEnum : uint { ... } actually works.)
Jeroen Landheer
Actually no. It inherits System.enum. As was posted before and more often here, what you think is inheritance is just a langauge dusambiguity in csharp.
TomTom
+13  A: 

You can achieve what you want with classes:

public class Base
{
    public const int A = 1;
    public const int B = 2;
    public const int C = 3;
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

Now you can use these classes similar as when they were enums:

int i = Consume.B;

Update (after your update of the question):

If you assign the same int values to the constants as defined in the existing enum, then you can cast between the enum and the constants, e.g:

public enum SomeEnum // this is the existing enum (from WSDL)
{
    A = 1,
    B = 2,
    ...
}
public class Base
{
    public const int A = (int)SomeEnum.A;
    //...
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;
M4N
+3  A: 

I have proposed a solution, a new class called EnumBuilder: http://www.codeproject.com/KB/cs/EnumBuilder.aspx.

Enjoy...

marcusts
A: 

The solutions above using classes with int constants lack type-safety. I.e. you could invent new values actually not defined in the class. Furthermore it is not possible for example to write a method taking one of these classes as input.

You would need to write

public void DoSomethingMeaningFull(int consumeValue) ...

However, there is a class based solution of the old days of Java, when there were no enums available. This provides an almost enum-like behaviour. The only caveat is that these constants cannot be used within a switch-statment.

public class MyBaseEnum
{
    public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
    public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
    public static readonly MyBaseEnum C = new MyBaseEnum( 3 );

    public int InternalValue { get; protected set; }

    protected MyBaseEnum( int internalValue )
    {
        this.InternalValue = internalValue;
    }
}

public class MyEnum : MyBaseEnum
{
    public static readonly MyEnum D = new MyEnum( 4 );
    public static readonly MyEnum E = new MyEnum( 5 );

    protected MyEnum( int internalValue ) : base( internalValue )
    {
        // Nothing
    }
}

[TestMethod]
public void EnumTest()
{
    this.DoSomethingMeaningful( MyEnum.A );
}

private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
    // ...
    if( enumValue == MyEnum.A ) { /* ... */ }
    else if (enumValue == MyEnum.B) { /* ... */ }
    // ...
}
Seven