Since I’m still working on a VB.NET I start to understand the language more and more. It feels like working with PHP. There are so many hacks, many things happen without you knowing that it happens.
Consider the following classes defined:
class Foo {}
class Bar : Foo
{
internal static Foo GetInstance()
{
return new Bar();
}
}
In C# you would have:
Console.WriteLine(Bar.GetInstance() as Bar);
the ‘as’ operator tries to cast foo to an instance of Bar. If that doesn’t succeed it returns null.
The code gets compiled to something like this:
{
Foo __foo = Bar.GetInstance();
Console.WriteLine(__foo is Bar ? (Bar)__foo : (Bar)null);
}
Doing a cast:
Console.WriteLine((Bar)Bar.GetInstance());
Throws an exception if we cannot cast. So you need to do a try catch around it.
Those are the casting operators in C#.
VB.NET has a little bit more stuff.
I will list them briefly:
CType(obj, Type), DirectCast(obj, Type), TryCast(obj, Type) and some predefined functions like CBool, CStr, Cint.
DirectCast(obj, Type) is the equivalent of the (Type)obj. No problem. TryCast(obj, Type) is the equivalent of obj as Type. No problem either. The problem arrises when we use CType and or one of those predefined functions.
You’d expect CBool(obj) to result in (you cannot do TryCast on a valuetype, hence the DirectCast) DirectCast(obj, Boolean). But no.
Consider the following code:
Dim boolTest As Object = False
Console.WriteLine(CBool(boolTest))
When compiled it gets converted to this:
Dim boolTest As Object
boolTest = CBool(0)
Console.WriteLine(Conversions.ToBoolean(boolTest))
You can take a look at the Conversions class with Reflector. It’s located in the Microsoft.VisualBasic dll (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.VisualBasic.dll) and the full name is Microsoft.VisualBasic.CompilerServices.Conversions.

CBool should just try a DirectCast in my opinion.
But CType has some more nuisances. We are still using the Foo and Bar classes defined above.
Consider this code:
Dim foo As Foo = Bar.GetInstance()
Console.WriteLine(CType(foo, Bar))
Gets compiled to:
Dim foo As Foo
Console.WriteLine(DirectCast(Bar.GetInstance, Bar))
Great, it uses DirectCast. So if the conversion fails it throws an exception…
Now the catch:
Dim test As Object = String.Empty
Console.WriteLine(CType(test, String))
You’d EXPECT it to do a DirectCast but no, this is what gets emmited:
Dim test As Object
Console.WriteLine(Conversions.ToString(String.Empty))
Again a roundtrip you don’t see…
That’s why I don’t like VB.NET. Too much happens behind the screens.
I know that you can program VB.NET without all of this (use DirectCast and TryCast yourself). But the problem is that all legacy developers use these functions because they don’t know better.
I wish these features where deprecated and only available for projects converted from VB6 code.