Casting and Converting in Visual Basic
When I wrote the “What a C# Coder Should Know Before They Write in VB” post, I had a log of feedback and conversations around conversions and casting. There are a number of casting and conversion operators in Visual Basic including three general purpose operators:
CType: Converts intrinsic types and any other types that have an overloaded CType operator. There is no comparable operator in C#. Throws and exception if the conversion cannot be completed.
DirectCast: Forces a cast. This is similar to the parentheses style - (newType)variableName cast in C#. Throws and exception if the type is not explicitly the type being cast.
TryCast: Attempts the cast and returns Nothing if it cannot be completed. Trycast never throws an exception.
As a summary:
|Operator ||Type ||C# Parallel ||Exception on Failure ||Usable on Value Types |
|CType ||Conversion ||None – use CLR ||Yes ||Yes |
|DirectCast ||Cast ||Parentheses style cast ||Yes ||Yes |
|TryCast ||Cast ||as operator ||No ||No |
DirectCast vs. parentheses style casting in C#: The C# parentheses style cast does an implicit widening cast, while DirecCast does not. This is particularly important when casting integers and floating point (single/double) values. This C# code compiles and runs:
Int32 z1 = 100000;
Int64 z2 = (Int64)z1;
While this VB code does not compile:
Dim i1 As Int32 = 100000
Dim i2 As Int64 = DirectCast(i1, Int64)
I’m a big fan of CType, although not all VB coders are. You can use it just about anytime and it just does the job in a simple, no thinking sort of way. It’s important to understand that it’s looking for any available conversion, including this one (which I wish I could turn off):
Dim k1 = "42"
Dim k2 = CType(k1, Int32)
But, I really don’t find myself making this mistake very often, and I’ll happily take the automatic conversions of one numeric into another.
CType is slower than DirectCast, but my tests have shown this to be a very negligible difference.
FxCop (and Static Analysis in Team System) like TryCast and the C# as operator over the comparable check of the type. I don’t think the static analysis tools catch whether you are using TryCast (or as) correctly:
Dim k4 = TryCast(k3, Class1(Of String))
If k4 IsNot Nothing Then
' do something with k4
Forgetting the check for nothing means you’ve got a null floating around simply because of the failed cast. This could cause some very unfortunate logic errors. You can accomplish the same thing with the TypeOf operator, but since TypeOf (and is in C#) actually perform the cast and throw away the result, you are wasting a few machine cycles when you use code like:
If TypeOf k3 Is Class1(Of String) Then
Dim k4 = DirectCast(k3, Class1(Of String))
The compiler may at some point be clever enough to optimize these two statements, but today it does not.
VB also has a large set of type specific conversion operators. Note that these are operators, not functions. The distinction is that they are present whether or not you have the Microsoft.VisualBasic namespace imported:
The CStr operator is slightly slower than ToString, but it is localization aware when dealing with dates as are the other VB operators such as CBool.
VB and C# also differ slightly in implicit conversions. For example implicit enum conversions are allowed in VB but not in C#:
Dim k8 = testEnum.Two
Dim k9 As Int32 = k8
In general, VB expands on the framework and C# conversions to offer globalization.