VB Curioddities #1: Enum, Enum, my kingdom for an Enum.Parse

Hey folks, my name’s Kit George and I’ve joined the VB team from the CLR. VB is after all, the best language, so of course, it makes sense to work directly on it!

Like all languages, VB has it’s little ‘oddities’, so i thought i would start a series to present a few of these. These are little (and perhaps large) curious VB things that you may or may not have noticed. Either way, you can bring them up at the water cooler to impress everyone with your VB knowledge.

I thought I would start with an interesting oddity surrounding Enum.Parse. Enum is of course, a keyword in Visual Basic, since it was already a keyword in days prior to .NET. This creates an interesting conflict between the Enum class (Enum is itself, a class in the System namespace of .NET), and the keyword. Why it becomes interesting is that the Enum class has some Shared members on it, most interestingly, Parse. You would normally invoke such a method with code like this:

  Public Class Test
  Public shared Sub Main()

    Dim ct as CarType = Enum.Parse(GetType(CarType), “Sedan”)
    MsgBox(ct)

  End Sub
 End Class

 Enum CarType
  Sedan = 1
  Sports = 2
  SUV = 3
 End Enum

However, because Enum is a keyword, you’ll get an exception on the above code because the ‘Enum.Parse’ line is treated as if you’re trying to declare an Enum by the compiler. You could workaround this easily by simply doing the followin. The square brackets around the name Enum tell the compiler to NOT treat it like a keyword, therefore, it treats it like a class call:

    Dim ct as CarType = [Enum].Parse(GetType(CarType), “Sedan”)

But in addition to the above syntax, and in order to make it even simpler, VB allows you to use the actual name of the Enum (CarType in this case) to invoke the Parse method. To all intents and purpose, this LOOKS like a Shared method call, so it should be supported:

    Dim ct as CarType = CarType.Parse(GetType(CarType), “Sedan”)

Now here’s where it gets interesting. Under the hood, the above line is actually turned into a call through to [Enum].Parse. That is, the CarType.Parse call has nothing to do with the CarType Enum itself, instead, it simply becomes a standard [Enum].Parse call. Therefore, what if I did something like this:

 Enum BoatType
  Trawler = 1
  SpeedBoat = 2
  CruiseShip = 3
 End Enum

    Dim ct as CarType = BoatType.Parse(GetType(CarType), “Sedan”)

Surely this wouldn’t compile, right? After all, it looks like we’re parsing on the BoatType class, into a CarType type: that surely doesn’t work.

But remember that CarType.Parse simply got turned into [Enum].Parse? Well, ANY other Enum call is the same. So BoatType.Parse, really just becomes [Enum].Parse. And this works just fine! So the above code compiles and runs just fine. Of course, I would not suggest under any circumstances, that you write your code this way, it is odd to read.

Note that of course, this will NOT work:

    Dim bt as BoatType = BoatType.Parse(GetType(CarType), “Trawler”)

The reason is that the KEY things for the transformation to succeed are that a) the type on the left of the assignment, and the type in the first parameter to the Parse method, match (they don’t in the above case, which is what causes it to fail), and b) that the string can be converted to the specified type (That is, it is a member of the specified Enum. In the above case it can, but of course, we’re gonna fail here because of item a) anyway).

At the end of the day, my own preference IS to use the name of the specific Enum, but simply use the same name as the Enum I’m parsing into. But I do like messing with people from time to time with this one ;-).