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.