Author Topic: DirectCast vs. CType vs. TryCast  (Read 14762 times)

0 Members and 1 Guest are viewing this topic.

willmswamp

  • Guest
DirectCast vs. CType vs. TryCast
« on: April 21, 2011, 12:08:03 PM »
DirectCast, CType, or TryCast ? 

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.

They seem similar but also seem to have subtle differences.

Thanks

n.yuan

  • Bull Frog
  • Posts: 348
Re: DirectCast vs. CType vs. TryCast
« Reply #1 on: April 21, 2011, 01:40:41 PM »
This article (and its readers' comments) may be helpful:

http://www.codeproject.com/KB/vb/DirectcastVsCtype.aspx

However, the article did not mention TryCase(). While DirectCast/CType may generate Excaption, if the original object type cannot be successfuly cast to the targeting object type, TryCast would return Nothing instead of raising Exception (equivalent to C# "As" keyword).

kaefer

  • Guest
Re: DirectCast vs. CType vs. TryCast
« Reply #2 on: April 22, 2011, 09:53:11 AM »
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.

CType is the odd one out, since it performs some dark magic outside of the CLR, and can be used to emulate Option Strict Off. An older article on msdn discusses this, under "Conversion Functions, CType, DirectCast, and System.Convert".

As for the others, it should be pretty straightforward to map type conversions between .NET languages.
VB.NETC#F#
upcast, inheritance or implementation required, can't failDirectCast(<type>):> or upcast
downcast, inheritance or implementation required, may throw InvalidCastExceptionDirectCast(<type>):?> or downcast
conversion, inheritance or implementation required, may return nullTryCastas <type>
type testTypeOfis <type>:?
type conversion functionsCInt, CDbl etc.int, float etc.

I'm not quite sure how conversions to and from System.Object (boxing/unboxing) fit into this picture.

Cheers, Thorsten

sinc

  • Guest
Re: DirectCast vs. CType vs. TryCast
« Reply #3 on: April 22, 2011, 11:44:08 AM »
I'm not quite sure how conversions to and from System.Object (boxing/unboxing) fit into this picture.

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.

Boxing and unboxing only comes into play when creating collections of type "Object".

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: DirectCast vs. CType vs. TryCast
« Reply #4 on: April 23, 2011, 01:29:29 AM »
I don't use VB, but

At the risk of stating the obvious

TryCast
http://msdn.microsoft.com/en-us/library/zyy863x8(v=VS.100).aspx
Quote
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).



CType
http://msdn.microsoft.com/en-us/library/4x2877xb(v=VS.100).aspx
Quote
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.


DirectCast
http://msdn.microsoft.com/en-us/library/7k6y2h6x(v=VS.100).aspx
Quote
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.

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: DirectCast vs. CType vs. TryCast
« Reply #5 on: April 23, 2011, 01:56:59 AM »
^^^ What he said ...

TryCast is my preferred method unless I am 100% certain of the object type before casting, then it is DirectCast ...

As I expressed in another thread somewhere around here, I prefer to code around problems than have to handle exceptions.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

Jeff H

  • Needs a day job
  • Posts: 6144
Re: DirectCast vs. CType vs. TryCast
« Reply #6 on: April 23, 2011, 05:45:12 PM »
I'm not quite sure how conversions to and from System.Object (boxing/unboxing) fit into this picture.
Cheers, Thorsten

A little confused here to and get different results from C# & VB

Boxing/ Unboxing happens when converting from value type to reference type and vise-versa.

I think the more formal definition is something like
Boxing - The CLR  creates a new heap-based object and copies the value from a value type to the new allocated object and then  returns a reference  to new object.
UnBoxing - The CLR copies a value from a reference type to a value type on the stack.
Something like that


I can not think of anyway else of doing this without the reference type being System.Object and how relates to System.ValueType

So anyone know why there is difference in the following examples  where VB does not unbox int32?

C#
Code: [Select]
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
    {


    }
}


IL from C#
Code: [Select]
.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



VB
Code: [Select]
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

IL From VB
Code: [Select]
.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




kaefer

  • Guest
Re: DirectCast vs. CType vs. TryCast
« Reply #7 on: April 25, 2011, 12:43:57 PM »
So anyone know why there is difference in the following examples  where VB does not unbox int32?

There's a call to CompilerServices.Conversions::ToInteger() and the stack return gets saved to local index 3 (int32 unboxingInt).

Much more interesting is the conditional for the last statement, is it a check for Nothing?

Quote
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.

What about the data types that aren't derived from System.Object?

There's a comprehensive description of their implicit conversions found in the C# Language Specification, under 4.3 Boxing and unboxing.