I would like to see a discussion on the differences, advantages, and different situations in which each of these are best used within the context of .NET programming for Autocad.
VB.NET | C# | F# | |
upcast, inheritance or implementation required, can't fail | DirectCast | (<type>) | :> or upcast |
downcast, inheritance or implementation required, may throw InvalidCastException | DirectCast | (<type>) | :?> or downcast |
conversion, inheritance or implementation required, may return null | TryCast | as <type> | |
type test | TypeOf | is <type> | :? |
type conversion functions | CInt, CDbl etc. | int, float etc. |
I'm not quite sure how conversions to and from System.Object (boxing/unboxing) fit into this picture.
Introduces a type conversion operation that does not throw an exception.
If an attempted conversion fails, CType and DirectCast both throw an InvalidCastException error. This can adversely affect the performance of your application. TryCast returns Nothing (Visual Basic), so that instead of having to handle a possible exception, you need only test the returned result against Nothing.
You use the TryCast keyword the same way you use the CType Function (Visual Basic) and the DirectCast Operator (Visual Basic) keyword. You supply an expression as the first argument and a type to convert it to as the second argument. TryCast operates only on reference types, such as classes and interfaces. It requires an inheritance or implementation relationship between the two types. This means that one type must inherit from or implement the other.
Errors and Failures
TryCast generates a compiler error if it detects that no inheritance or implementation relationship exists. But the lack of a compiler error does not guarantee a successful conversion. If the desired conversion is narrowing, it could fail at run time. If this happens, TryCast returns Nothing (Visual Basic).
Returns the result of explicitly converting an expression to a specified data type, object, structure, class, or interface.
CType(expression, typename)
expression
Any valid expression. If the value of expression is outside the range allowed by typename, Visual Basic throws an exception.
typename
Any expression that is legal within an As clause in a Dim statement, that is, the name of any data type, object, structure, class, or interface.
CType is compiled inline, which means that the conversion code is part of the code that evaluates the expression. In some cases there is no call to a procedure to accomplish the conversion, which makes execution faster.
If no conversion is defined from expression to typename, for example from Integer to Date, Visual Basic displays a compile-time error message.
If a conversion fails at run time, the appropriate exception occurs. If a narrowing conversion fails, an OverflowException is the most common result. If the conversion is undefined, an InvalidCastException occurs. This can happen, for example, if expression is of type Object and its run-time type has no conversion to typename.
If the data type of expression or typename is a class or structure you have defined, you can define CType on that class or structure as a conversion operator. This makes CType act as an overloaded operator. If you do this, you can control the behavior of conversions to and from your class or structure, including what exceptions can be thrown.
Overloading
The CType operator can also be overloaded on a class or structure defined outside your code. If your code converts to or from such a class or structure, be sure you understand the behavior of its CType operator. For more information, see Operator Procedures (Visual Basic).
Converting Dynamic Objects
If you are working with dynamic objects, where type conversions are performed by user-defined dynamic conversions that use the TryConvert or BindConvert methods, Use the CTypeDynamic method to convert the dynamic object.
Introduces a type conversion operation based on inheritance or implementation.
DirectCast does not use the Visual Basic run-time helper routines for conversion, so it can provide somewhat better performance than CType when converting to and from data type Object.
You use the DirectCast keyword the same way you use the CType Function (Visual Basic) and the TryCast Operator (Visual Basic) keyword. You supply an expression as the first argument and a type to convert it to as the second argument. DirectCast requires an inheritance or implementation relationship between the data types of the two arguments. This means that one type must inherit from or implement the other.
Errors and Failures
DirectCast generates a compiler error if it detects that no inheritance or implementation relationship exists. But the lack of a compiler error does not guarantee a successful conversion. If the desired conversion is narrowing, it could fail at run time. If this happens, the runtime throws an InvalidCastException error.
I'm not quite sure how conversions to and from System.Object (boxing/unboxing) fit into this picture.
Cheers, Thorsten
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BoxingCSharp
{
public class BoxCsharp
{
static void Main(string[] args)
{
int number = 5;
[color=red]object boxing = number;[/color]
object unboxObject = 5;
[color=blue]int unboxingInt = (int)unboxObject; [/color]
ValType vt;
[color=red]object oVtBox = vt;[/color]
[color=blue]ValType vtUnBox = (ValType)oVtBox;[/color]
}
}
struct ValType
{
}
class RefType : Object
{
}
}
.method private hidebysig static void Main(string[] args) cil managed
{
// Code size 43 (0x2b)
.maxstack 1
.locals init ([0] int32 number,
[1] object boxing,
[2] object unboxObject,
[3] int32 unboxingInt,
[4] valuetype BoxingCSharp.ValType vt,
[5] object oVtBox,
[6] valuetype BoxingCSharp.ValType vtUnBox)
IL_0000: nop
IL_0001: ldc.i4.5
IL_0002: stloc.0
IL_0003: ldloc.0
[color=red] IL_0004: box [mscorlib]System.Int32[/color]
IL_0009: stloc.1
IL_000a: ldc.i4.5
IL_000b: box [mscorlib]System.Int32
IL_0010: stloc.2
IL_0011: ldloc.2
[color=blue] IL_0012: unbox.any [mscorlib]System.Int32[/color]
IL_0017: stloc.3
IL_0018: ldloc.s vt
[color=red] IL_001a: box BoxingCSharp.ValType[/color]
IL_001f: stloc.s oVtBox
IL_0021: ldloc.s oVtBox
[color=blue]IL_0023: unbox.any BoxingCSharp.ValType[/color]
IL_0028: stloc.s vtUnBox
IL_002a: ret
} // end of method BoxCsharp::Main
Namespace BoxingVB
Public Class BoxVB
Private Shared Sub Main(args As String())
Dim number As Int32 = 5
[color=red]Dim boxing As Object = number[/color]
Dim unboxObject As Object = 5
[color=green]'??????????????????????????????????[/color]
[color=blue]Dim unboxingInt As Int32 = unboxObject[/color]
[color=green] '??????????????????????????????????[/color]
Dim vt As ValType
[color=red]Dim oVtBox As Object = vt[/color]
[color=blue] Dim vtUnBox As ValType = oVtBox[/color]
End Sub
End Class
Structure ValType
End Structure
Class RefType
Inherits Object
End Class
End Namespace
.method private static void Main(string[] args) cil managed
{
// Code size 57 (0x39)
.maxstack 2
.locals init ([0] object boxing,
[1] int32 number,
[2] object oVtBox,
[3] int32 unboxingInt,
[4] object unboxObject,
[5] valuetype BoxingVB.BoxingVB.ValType vt,
[6] valuetype BoxingVB.BoxingVB.ValType vtUnBox,
[7] valuetype BoxingVB.BoxingVB.ValType VB$t_struct$N0)
IL_0000: nop
IL_0001: ldc.i4.5
IL_0002: stloc.1
IL_0003: ldloc.1
[color=red]IL_0004: box [mscorlib]System.Int32[/color] IL_0009: stloc.0
IL_000a: ldc.i4.5
IL_000b: box [mscorlib]System.Int32
IL_0010: stloc.s unboxObject
IL_0012: ldloc.s unboxObject
IL_0014: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToInteger(object)
IL_0019: stloc.3
IL_001a: ldloc.s vt
[color=red]IL_001c: box BoxingVB.BoxingVB.ValType[/color]
IL_0021: stloc.2
IL_0022: ldloc.2
IL_0023: dup
IL_0024: brtrue.s IL_002b
IL_0026: pop
IL_0027: ldloc.s VB$t_struct$N0
IL_0029: br.s IL_0035
[color=blue]IL_002b: unbox BoxingVB.BoxingVB.ValType[/color]
IL_0030: ldobj BoxingVB.BoxingVB.ValType
IL_0035: stloc.s vtUnBox
IL_0037: nop
IL_0038: ret
} // end of method BoxVB::Main
So anyone know why there is difference in the following examples where VB does not unbox int32?
Code: [Select]Dim vtUnBox As ValType = oVtBox
System.Object is the root class of the .NET object hierarchy. In other words, it's a parent class, and all other objects are derived from it.