Since I'm on the cusp of rewriting the section in the VB language spec on DirectCast
so that it actually tries to make sense, I thought I'd talk about it here, since I
don't know how much people understand about this strange little operator. DirectCast
is a cast operator that has the same syntax as CType and is useful in some narrow
situations. But first, a little background...
You may have noticed that all VB.NET projects get a default reference to Microsoft.VisualBasic.DLL.
It doesn't show up in your list of references because you can't remove it. Why? Because
it isn't possible to express all of the VB language in IL, so we sometimes have to
rely on helper functions. A good example of this is conversions from Object.
If you convert an Integer to Object, for example, the CLR will only let you convert
it back to Integer. However, VB will allow you to convert it back to Long, Double,
String, etc. To make this work, the compiler emits a conversion from Object
as a call to a helper function. The helper function takes the Object, looks
at the type of the value contained in it and then does the appropriate conversion
to the target type.
When we started working on Microsoft.VisualBasic.DLL, we decided to write all the
language helpers (and all the familiar user functions like Left, Right, Mid, etc)
in VB. In addition to the fact that we like VB, it's also a great way to
dogfood the product. So we set about writing the helpers, but we quickly ran into
a chicken-and-egg problem. Let's say that we're writing the helper that converts something
typed as Object to Integer. It would contain code something like:
If TypeOf o Is Integer Then
Return CInt(o)
End If
See the problem? The CInt(o) conversion tries to convert something typed as Object
to Integer... which is going to call the helper again. And again. And again. Until
you run out of stack space and die. The problem was there was no way to "escape" from
the extra VB conversion semantics and say "just cast this directly to x type,
forget about all the fancy stuff." And that's where DirectCast comes in. The function
of DirectCast is to just give you the CLR supported conversions and none of the
extra conversions that VB supports by use of a helper. So when you say DirectCast(o,
Integer), if o does not contain an Integer, you'll get an exception, whereas CType(o,
Integer) will work if o contains a Long, Double, String, etc. As you can imagine,
we use this all over the place in our helpers.
Ok, so now you're asking: "So why isn't this just something you hacked in for building
your runtime? Why did you make it a full part of the language?" Well, one reason was
that we wanted to follow the principle that we didn't want to have to "cheat" to build
our runtime - presumably, if we needed to do something, others might, too. (There
are still a few minor cheats that we make when building our runtime, but that's another
blog entry.) And, as it turns out, there are some narrow situations where using DirectCast
can make things a tiny bit fast than they might otherwise be. Essentially, if you know that
what you're converting is exactly what you say it is, then you can use DirectCast
to bypass the little bit of overhead that you incur by using the runtime helper. The
most common place I use it in my own code is when dealing with collections like ArrayList:
Dim a As New ArrayList()
Dim i As Integer
a.Add(42)
i = DirectCast(a(0), Integer)
In this case, I know that the thing I'm getting out of the ArrayList is an
Integer, so I skip the helper and go straight to DirectCast. However, I only suggestion
you use this in situations where you know it will work, and you think you need that
extra little bit of performance. In the real world, you're hardly ever going to notice
the difference, so you might as well go with the more flexible conversion operators
like CType, CInt, etc. But when you identify some place you need that extra little
"oomph," it can come in handy.