C#: Dynamic Runtime Cast

C#: Dynamic runtime cast

I think you're confusing the issues of casting and converting here.

  • Casting: The act of changing the type of a reference which points to an object. Either moving up or down the object hierarchy or to an implemented interface
  • Converting: Creating a new object from the original source object of a different type and accessing it through a reference to that type.

It's often hard to know the difference between the 2 in C# because both of them use the same C# operator: the cast.

In this situation you are almost certainly not looking for a cast operation. Casting a dynamic to another dynamic is essentially an identity conversion. It provides no value because you're just getting a dynamic reference back to the same underlying object. The resulting lookup would be no different.

Instead what you appear to want in this scenario is a conversion. That is morphing the underlying object to a different type and accessing the resulting object in a dynamic fashion. The best API for this is Convert.ChangeType.

public static dynamic Convert(dynamic source, Type dest) {
return Convert.ChangeType(source, dest);
}

EDIT

The updated question has the following line:

obj definitely implements castTo

If this is the case then the Cast method doesn't need to exist. The source object can simply be assigned to a dynamic reference.

dynamic d = source;

It sounds like what you're trying to accomplish is to see a particular interface or type in the hierarchy of source through a dynamic reference. That is simply not possible. The resulting dynamic reference will see the implementation object directly. It doesn't look through any particular type in the hierarchy of source. So the idea of casting to a different type in the hierarchy and then back to dynamic is exactly identical to just assigning to dynamic in the first place. It will still point to the same underlying object.

Why is casting with dynamic faster than with object

You can have a look at IL code to see the difference under the hood. Object cast

public TEnum ObjectCast()
{
return (TEnum)(object)0;
}

box int value into object and then unbox into TEnum value, since it's value type

IL_0001: ldc.i4.0
IL_0002: box [System.Runtime]System.Int32
IL_0007: unbox.any TestConsoleApp.Test/TEnum
IL_000c: stloc.0 // V_0
IL_000d: br.s IL_000f

I guess that it's a main reason of the slowest execution in comparison with other samples.

The dynamic object cast

public TEnum DynamicCast()
{
return (TEnum) (dynamic) 0;
}

looks more complicated

IL_0001: ldsfld       class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>> TestConsoleApp.Test/'<>o__0'::'<>p__0'
IL_0006: brfalse.s IL_000a
IL_0008: br.s IL_002f
IL_000a: ldc.i4.s 16 // 0x10
IL_000c: ldtoken TestConsoleApp.Test/TEnum
IL_0011: call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
IL_0016: ldtoken TestConsoleApp.Test
IL_001b: call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
IL_0020: call class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, class [System.Runtime]System.Type, class [System.Runtime]System.Type)
IL_0025: call class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<!0/*class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>*/> class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>>::Create(class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSiteBinder)
IL_002a: stsfld class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>> TestConsoleApp.Test/'<>o__0'::'<>p__0'
IL_002f: ldsfld class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>> TestConsoleApp.Test/'<>o__0'::'<>p__0'
IL_0034: ldfld !0/*class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>*/ class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>>::Target
IL_0039: ldsfld class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite`1<class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>> TestConsoleApp.Test/'<>o__0'::'<>p__0'
IL_003e: ldc.i4.0
IL_003f: box [System.Runtime]System.Int32
IL_0044: callvirt instance !2/*valuetype TestConsoleApp.Test/TEnum*/ class [System.Runtime]System.Func`3<class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite, object, valuetype TestConsoleApp.Test/TEnum>::Invoke(!0/*class [System.Linq.Expressions]System.Runtime.CompilerServices.CallSite*/, !1/*object*/)
IL_0049: stloc.0 // V_0
IL_004a: br.s IL_004c

There is a type information loaded, then instance of CallSiteBinder is initialized using Binder.Convert static method. Then an instance of generic CallSite class is created, using Create static call (ldsfld pushes the value of static field into the stack). I'm not 100% sure, but the generic argument Func<CallSite, object, TEnum means a function, which will be invoked to convert the object into TEnum. Last lines show that this function is bound to TEnum class.

So, under the hood compiler already creates you a method to cast a dynamic object to required TEnum type. And there is only boxing operation from int to object to pass it to created function. This sounds like a good reason, why it's faster than object cast with boxing and unboxing operations

Dynamic cast at runtime

No. You can't cast to any type that is unknown at compile time. However, c# does have a special keyword for declaring variables of a type that is unknown - it's dynamic.

You can think of it like a form of late binding - The actual type of the variable is determind at run time only.

When you declare a dynamic variable, c# compiler actually creates a variable of type object, but does not perform any type checking.

The dynamic type enables the operations in which it occurs to bypass compile-time type checking. Instead, these operations are resolved at run time.

...

Type dynamic behaves like type object in most circumstances. However, operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. As part of the process, variables of type dynamic are compiled into variables of type object. Therefore, type dynamic exists only at compile time, not at run time.

c# dynamic casting or conversion

1)You can iterate over the array

 double[] data = new double[] { 1, 2, 3 };
foreach (var item in data)
Console.WriteLine(item.ToString());

2)Or

 Console.WriteLine(string.Join(",", data)); 

The above solutions work if you already have an array of double.
In your case ,if you are sure that data[0] is an array of double you can use the as operator

double[] temp = data[0] as double[];
Console.WriteLine(string.Join(",", temp));

Dynamic object cast to type known at runtime only

Casting to a type that's known only at Runtime seems to be a senseless operation for the compiler: since by definition it doesn't know the type until Runtime, there's no compile-time support for it so there's no benefit in doing so. If the object is used through Reflection, then the actual Type of the variable that holds the instance doesn't matter much - might as well be Object.

That doesn't mean it's not possible, it's just a bit cumbersome to do the cast. The language does allow us to write code that's only made aware of a given type at Runtime, using type-parametrised types!

The code in my example sets a very simple method to obtain an AdapterDelegate for a LibraryDelegate<TRunTimeType>, using information exclusively found at runtime. You'll notice the actual cast to TRunTimeType in the AdapterDelegateHelper.Adapter<TRuntimeType>.adapter method. Look at the Main code to see how easy this is to use:

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection;

namespace ConsoleApplication2
{
// Start by declaring a delegate that looks exactly like the library method you want to call, but with TRuntimeType in place of the actual type
public delegate void LibraryDelegate<TRuntimeType>(TRuntimeType param, Int32 num, String aStr);
// Declare an "adapter" delegate that uses "Object" in place of TRuntimeType for every relevant parameter
public delegate void AdapterDelegate(Object param, Int32 num, String aStr);

public static class AdapterDelegateHelper
{
private class Adapter<TRuntimeType>
{
private readonly LibraryDelegate<TRuntimeType> libDelegate;

public Adapter(Object LibraryInstance, String MethodName)
{
Type libraryType = LibraryInstance.GetType();
Type[] methodParameters = typeof(LibraryDelegate<TRuntimeType>).GetMethod("Invoke").GetParameters().Select(p => p.ParameterType).ToArray();
MethodInfo libMethod = libraryType.GetMethod(MethodName, methodParameters);
libDelegate = (LibraryDelegate<TRuntimeType>) Delegate.CreateDelegate(typeof(LibraryDelegate<TRuntimeType>), LibraryInstance, libMethod);
}

// Method that pricecly matches the adapter delegate
public void adapter(Object param, Int32 num, String aStr)
{
// Convert all TRuntimeType parameters.
// This is a true conversion!
TRuntimeType r_param = (TRuntimeType)param;

// Call the library delegate.
libDelegate(r_param, num, aStr);
}
}

public static AdapterDelegate MakeAdapter(Object LibraryInstance, String MethodName, Type runtimeType)
{
Type genericType = typeof(Adapter<>);
Type concreteType = genericType.MakeGenericType(new Type[] { runtimeType });
Object obj = Activator.CreateInstance(concreteType, LibraryInstance, MethodName);
return (AdapterDelegate)Delegate.CreateDelegate(typeof(AdapterDelegate), obj, concreteType.GetMethod("adapter"));
}
}

// This class emulates a runtime-identified type; I'll only use it through reflection
class LibraryClassThatIOnlyKnowAboutAtRuntime
{
// Define a number of oberloaded methods to prove proper overload selection
public void DoSomething(String param, Int32 num, String aStr)
{
Console.WriteLine("This is the DoSomething overload that takes String as a parameter");
Console.WriteLine("param={0}, num={1}, aStr={2}", param, num, aStr);
}

public void DoSomething(Int32 param, Int32 num, String aStr)
{
Console.WriteLine("This is the DoSomething overload that takes Integer as a parameter");
Console.WriteLine("param={0}, num={1}, aStr={2}", param, num, aStr);
}

// This would be the bad delegate to avoid!
public void DoSomething(Object param, Int32 num, String aStr)
{
throw new Exception("Do not call this method!");
}
}

class Program
{

static void Main(string[] args)
{
Type castToType = typeof(string);
Type libraryTypeToCall = typeof(LibraryClassThatIOnlyKnowAboutAtRuntime);

Object obj = Activator.CreateInstance(libraryTypeToCall);

AdapterDelegate ad1 = AdapterDelegateHelper.MakeAdapter(obj, "DoSomething", castToType);
ad1("param", 7, "aStr");

Console.ReadKey();
}
}
}

How does casting from dynamic object works in C#

Your code...

object o = new { Name = "test" };
SampleClass casted = (SampleClass)(dynamic)o; // this won't work

...does not work, not because of the intermediate cast to dynamic, but because of the type mismatch between your anonymous class and SampleClass.

Do not confuse dynamic with anonymous classes. There are no objects of type dynamic, it is mainly just there for the compiler. On the other hand, anonymous classes are full type-safe classes that exist at compile time. There is no difference to non-anonymous classes, except that you don't know the name. The compiler will create a full class definition under the hood (check with a decompiler).

This is also the problem with your assignment. You are tryig to assign an object of your anonymous class to a variable of type SampleClass. This can not work (and it doesn't matter that they share the Name property). You can just as well try to assign a string, int or any other type (except SampleClass), the result will be exactly the same.

Always keep in mind that C# is strongly typed. In weakly typed languages like JavaScript, your assignment would work. Not so in C#.

UPDATE (with information from the question's comments):

Your assignment...

SalesOrder readOrder = (SalesOrder)(dynamic)response.Resource;

...is different in an important aspect. The converted type implements the IDynamicMetaObjectProvider interface. The cast to dynamic makes the compiler recognize this interface. It can then inject code to do a conversion to SalesOrder using that interface. It will result in completely different code that will perform a dynamic runtime conversion of the source object that has nothing to do with a regular typecast.



Related Topics



Leave a reply



Submit