For your situation, TryCast
with an IsNot Nothing
check might be more beneficial.
To understand when and why to use which, though, first take a look at the MSDN definitions of them.
DirectCast
Introduces a type conversion operation based on inheritance or implementation. ... DirectCast does not use the Visual Basic run-time helper routines for conversion...
CType
Returns the result of explicitly converting an expression to a specified data type, object, structure, class, or interface.
Implicit Conversion
An implicit conversion does not require any special syntax in the source code. ... An explicit conversion uses a type conversion keyword
TryCast
Introduces a type conversion operation that does not throw an exception. ... TryCast returns Nothing (Visual Basic), so that instead of having to handle a possible exception, you need only test the returned result against Nothing.
Going off of those definitions, we can assume that CType
will make an external call based on a given System.Type
, while DirectCast
will just use the existing object under a different moniker. Meanwhile, with implicit conversion, VB will just try to execute the code. TryCast
, however, will try to cast the object or just return Nothing
(think of the C# as
operator)
For example:
' works
Dim obj As Object = "I'm a string!" 'obj.GetType() -> System.String
Dim s = DirectCast(obj, String)
' throws error: Unable to cast object of type 'System.Int32' to type 'System.String'.
Dim obj As Object = 42 'obj.GetType() -> System.Int32
Dim s = DirectCast(obj, String)
The first example works, because obj
is already a String
that has just been defined as an Object
. No actual conversion is taking place.
Now let's look at CType
:
' works
Dim obj As Object = "I'm a string!" 'obj.GetType() -> System.String
Dim s = CType(obj, String)
' works - would prefer to use CStr() here instead, since it's more explicit (see below)
Dim obj As Object = 42 'obj.GetType() -> System.Int32
Dim s = CType(obj, String)
And finally, implicit conversion:
' works with Option Explicit. Throws build error with Option Strict: Option Strict On disallows implicit conversions from 'Object' to 'String'.
Dim obj As Object = "I'm a string!" 'obj.GetType() -> System.String
Dim s As String = obj
' same as above
Dim obj As Object = 42 'obj.GetType() -> System.Int32
Dim s As String = obj
Both of these work, but remember that VB.NET is calling a separate library here to do the dirty work:
DirectCast:
IL_0000: nop
IL_0001: ldstr "I'm a string!"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: castclass [mscorlib]System.String
IL_000d: stloc.1
IL_000e: nop
IL_000f: ret
CType/Implicit Conversion (compiles the same):
IL_0000: nop
IL_0001: ldstr "I'm a string!"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToString(object)
IL_000d: stloc.1
IL_000e: nop
IL_000f: ret
So, basically, due to .NET needing to call external methods to determine what it needs to do to convert the object, CType
/implicit will run somewhat slower (example benchmarks and examples here). Note, since they both compile the same in MSIL, CType
and implicit conversion should perform identically.
So when do you use them? I generally follow a couple simple rules
- If I know (or expect) my object is already my target type, just defined differently, I use
DirectCast
- If my object is different type than my target type, I use the appropriate Convert method. Example:
Dim myInt = CInt("42")
. Note, this compiles the same way as CType
in the IL
- If I am unsure of the incoming type, I use
TryCast
- If I'm casting/converting with generics, I'll use
DirectCast
and/or Convert.ChangeType
, depending on the context
You could also use CType
for the second one there, but in my opinion, if I know I'm converting to an Integer
, then I'll choose the more explicit CInt
. If you have Option Strict
on, though, you should get a build error either way if you pass the wrong thing into either.
Also, while you might tempted to try substituting TryCast
for DirectCast
check the answer to this SO question regarding major differences and uses: Why use TryCast instead of Directcast?
If you notice, I did not include implicit typing in there. Why? Well, mostly because I code with Option Strict On
, and it doesn't really allow implicit conversions when narrowing types (see "Widening and Narrowing Conversions"). Otherwise, as far as the .NET is concerned, it's pretty much identical to CType
Ok, now that all of that's done, let's look at all three (four, I guess) with Control
objects:
' control is just defined as a regular control
Dim control As New Control
' Runtime Error: Unable to cast object of type 'System.Web.UI.Control' to type 'System.Web.UI.LiteralControl'
Dim literal_1 As LiteralControl = DirectCast(control, LiteralControl)
' Runtime Error: Unable to cast object of type 'System.Web.UI.Control' to type 'System.Web.UI.LiteralControl'
Dim literal_2 As LiteralControl = CType(control, LiteralControl)
' returns literal_3 -> Nothing
Dim literal_3 As LiteralControl = TryCast(control, LiteralControl)
And one more:
' control as a LiteralControl stored as a Control
Dim control As Control = New LiteralControl
' works
Dim literal_1 As LiteralControl = DirectCast(control, LiteralControl)
' works
Dim literal_2 As LiteralControl = CType(control, LiteralControl)
' works
Dim literal_3 As LiteralControl = TryCast(control, LiteralControl)
So, for your situation, it looks like TryCast
with a IsNot Nothing
check is the way to go.