A Note about Enums (Scott Wisniewski)

A Note about Enums (Scott Wisniewski)

  • Comments 3

I recently received an email from a customer who had a few questions about "enum inheritance" in VB, specifically as to why it wasn't supported. In particular, he sent us the following snippet of VB code  (I've changed the names of the classes and methods involved)  :

Option Strict On

Public Class BaseClass

   
Public Enum SomeEnum
        Value1
        Value2
   
End Enum

   
Public Overridable Sub DoSomething(ByVal e As SomeEnum)
       
Select Case e
           
Case SomeEnum.Value1
                DoSomething1()
           
Case SomeEnum.Value2
                DoSomething2()
        
End Select
   
End Sub

    Private Sub DoSomething1()
   
End Sub

   
Private Sub DoSomething2()
   
End Sub

End Class

Public Class DerivedClass
   
Inherits BaseClass

   
Public Shadows Enum SomeEnum
        Value1
        Value2
        Value3
   
End Enum

   
Public Shadows Sub DoSomething(ByVal e As SomeEnum)
       
Select Case e
           
Case SomeEnum.Value1, SomeEnum.Value2
                MyBase.DoSomething(CType(e, BaseClass.SomeEnum))
            
Case SomeEnum.Value3
                DoSomething3()
        
End Select
   
End Sub

    Private Sub DoSomething3()
   
End Sub

End Class



and asked us the following questions:

  1. Why does SomeEnum have to be marked as shadows inside DerivedClass? Why can't I use "overloads"?
  2. Why does DerivedClass.DoSomething() have to cast it's enum value to the value in the base class.

I figured other people may have run into similar issues any may have some of the same questions, and so though this would make a good blog post.

My response is below:


VB does not support "Enum" inheritance, and so it is not possible for one Enum type to inherit from another "Enum" type.

This is mainly because "Enum" inheritance is not safe. In general, an inheritance relationship between two types implies that it is possible to always treat a "more specific" derived class as if it was also a "more general" base class. This relationship does not hold between two enums.

This is because, enum's are really not object-oriented concepts. Instead, an enum is just a collection of constant variable declarations conveniently packaged into a type. What defines the "identity" of an enum is the set of values it may take.

In general, if you were to take an enum like so:

Enum Foo 
Value1
Value2
End Enum

 

and then try to extend it with inheritance like so (this is not legal):

Enum FooDerived Inherits Foo 
Value3
End Enum

 

It would no longer be possible to say that "any FooDerived" is also a "Foo". This is because the value "Value3" cannot be treated as if it was a "Foo" value.

The compiler does, for convenience, provide conversions between different enum types. This is because in the event that you know the value your are converting can be represented in the target type then it is safe to do the conversion. Because it is not always safe, however, the conversion is treated as a "narrowing" (unsafe) conversion rather than a "widening" (safe) conversion.

When "option strict" is turned on the compiler will not implicitly perform unsafe conversions. Instead it requires you to explicitly tell it when a potentially unsafe conversion is in fact safe by writing an explicit "CType".

Marking the SomeEnum type DerivedClass as shadows makes it a completely new enum type from the one defined in "BaseClass". Because "BaseClass.SomeEnum" and "DerivedClass.SomeEnum" are different enum types, the conversion is not safe, and thus requires an explicit cast.

Leave a Comment
  • Please add 1 and 6 and type the answer here:
  • Post
  • PingBack from http://msdnrss.thecoderblogs.com/2007/10/15/a-note-about-enums-scott-wisniewski/

  • I believe I got the context of the question, but I feel that the answer slightly misses the point. While technically correct, the problem in the question would IMHO better be solved by following a few simple principles leading to better code in the first place.

    Extract what varies. In this case the variation is the DoSomethingXXX().

    If the base class had a reference to an IDoSomething.

    eg. Dim MyDoer as IDoSomething

    then instead of switching on the enum he could just call MyDoer.DoSomething where the MyDoer is a concrete implementation of whatever action needs to be carried out.

    This would also shield the base class from changes when a DoSomethingXYZ comes around.

  • While I can see why you can't inherit from enum types, what I'd really like do is constrain on enum types, such as:

    Public Class Foo(Of T As System.Enum)

    ...

    End Class

    This would ensure that T will be supported in the System.Enum.GetNames() method, for example. Plus, you can always cast it to an Object.

Page 1 of 1 (3 items)