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
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
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
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
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
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
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
CInt, etc. But when you identify some place you need that extra little “oomph,” it can come in handy.