Casting in Visual Basic .NET

In all type safe languages there is the concept of “casting”, an operation used to specify to the compiler that a variable of a certain Type has to be considered of different Type. Visual Basic has three operators to do a cast: DirectCast, CType and TryCast, each one behaving in a different way from the other. To understand the subtle differences from these three operators lets present a simple example.

   Private Sub DirectCastExample(ByVal obj As Object)
      Console.WriteLine(
“string lenght={0}”, DirectCast(obj, String).Length)
   
End Sub
 
   
Private Sub CTypeExample(ByVal obj As Object)
      Console.WriteLine(
“string lenght={0}”, CType(obj, String).Length)
   
End Sub
 
   
Private Sub trycastExample(ByVal obj As Object)
      Console.WriteLine(
“string lenght={0}”, TryCast(obj, String).Length)
   
End Sub

   Private Sub Test()
      DirectCastExample(30)
      CTypeExample(30)
      trycastExample(30)
   
End Sub

The three instruction of the Test() function give really three different results, the first throws an InvalidCastException, the second writes “string length=2” and the third throws a NullReferenceException. To understand what is happening we could look at generated MSIL . DirectCast operator is translated with this code

L_0007: castclass string
L_000c: callvirt instance int32 [mscorlib]System.String::get_Length()

DirectCast is translated to castclass opcode, that simply pushes on the stack the object reference to the cast instance. If at run time the instance passed to the function is not a String class an InvalidCastException is thrown. DirectCast can convert if the object is of the exact type, if inherits from the type specified, or if the object implements the interface when the destination type is an interface.

TryCast operator behaves a little different, this is the MSIL generated

L_0007: isinst string
L_000c: callvirt instance int32 [mscorlib]System.String::get_Length()

TryCast use the isinst opcode, that is analogous to castclass, but if the cast is not successful instead of throwing an exception a null value is push on the stack. The third type of cast, CType is not really a cast operator, but instead a conversion operator, even if in a lot of documentation CType is considered to be a cast operator, to understand the difference here is generated MSIL.

L_0007: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToString(object)
L_000c: callvirt instance int32 [mscorlib]System.String::get_Length()

As you can see CType operator calls internally the function ToString() of class Microsoft.VisualBasic.CompilerServices.Conversions, this means that CType does not make a cast, but it makes conversions. The example in fact reveals that when we pass the integer value 30 to the function, this value gets converted to the string “30” and the code does not throw errors. The annoying issue is that you use CType to convert a variable to a custom type class it defaults to use castclass opcode, since the Microsoft.VisualBasic.CompilerServices.Conversion has methods to convert only to .NET basic types.

Alk.

Â

Â

Published by

Ricci Gian Maria

.Net programmer, User group and community enthusiast, programmer - aspiring architect - and guitar player :). Visual Studio ALM MVP

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.