Search code examples
c#castingoperator-overloadingreflection.emitdynamic-code

Is it possible to have implicit conversion operators being called during casts made by a method generated dynamically ? (eg: IL emit)


I have have the following classes A and B:

public class A 
{
}
    
public class B  
{
    public static implicit operator A(B value)
    {
        return new A();
    } 
}

As expected, the following code compiles and runs fine (no exceptions):

A a = new B();

Same for:

B b = new B();
A a = (A)b;

However, if I create a method that does similar cast at runtime (by emitting IL) it fails :

DynamicMethod method = new DynamicMethod("", typeof(A), new [] { typeof(B) });
ILGenerator gen = method.GetILGenerator();

gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Castclass, typeof(A)); //actual cast
gen.Emit(OpCodes.Ret);    
Func<B, A> fn = (Func<B, A>)method.CreateDelegate(typeof(Func<B, A>));

A instance = fn(new B());

This is supposed to be the equivalent of (but it's not):

Func<B, A> fn = x => (A)x;

Here is what I got :

InvalidCastException: Unable to cast object of type 'B' to type 'A'.

It looks like implicit cast is something purely resolved at compile time (some kind of synthetic sugar) and the regular cast (that looks through types hierarchy and checks it cast can be made) is not aware of it. Can somebody confirm it ?

Is there a workaround ? I ask this because I use a library (not written by me) that maps some types using generated code (IL). I expected implicit casts to work (be called automatically by the library) but it does not.


Solution

  • You need the following

    gen.Emit(OpCodes.Call, typeof(B).GetMethod("op_Implicit"));
    

    Implicit casts are operators, which are compiled as special static methods.