The explicit cast operator applied to an instance created by reflection

I was surprised to find that the following code throws an exception at runtime:

class A { public string Name { get; set; } public A() { Name = "Class A"; } } class B { public string Name { get; set; } public B() { Name = "Class B"; } public static explicit operator A(B source) { return new A() {Name = source.Name}; } } class Program { static void Main(string[] args) { // This executes with no error var bInstance = new B(); Console.WriteLine(bInstance.GetType()); // <assemblyname>.B var aInstance = (A) bInstance; Console.WriteLine(aInstance.Name); // Class B // This fails with InvalidCastException var bInstanceReflection = Activator.CreateInstance(typeof (B)); Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B var aInstanceReflection = (A) bInstanceReflection; Console.WriteLine(aInstanceReflection.Name); } } 

Can someone tell me why? I really don't understand what happened.

+4
source share
3 answers

Do not be surprised - user statements do not override anything, they are overloaded - therefore, they are selected at compile time, rather than at run time.

When we remove implicit text input from code, this makes it more understandable:

 object bInstanceReflection = Activator.CreateInstance(typeof (B)); Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B A aInstanceReflection = (A) bInstanceReflection; 

Now it’s clear enough that the last line (A) is just different from the object , which performs a normal reference conversion. No custom conversions will be applied at all.

If you are using .NET 4, you can use dynamic typing to make it work:

 // Note the change of type dynamic bInstanceReflection = Activator.CreateInstance(typeof (B)); Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B A aInstanceReflection = (A) bInstanceReflection; 

Now the transformation is applied to the dynamic value, which means that the choice of which transformation in use is delayed until runtime is at that moment it will use your custom operator.

+7
source

You have created B Then translate it to A

Despite similar layouts, B has nothing to do with A. Static operators are used by the compiler, but not at runtime via cast. Although the syntax of C # is the same, they are very different in reflection.

This is the normal expected behavior.

+3
source

You can simply change this line:

 var bInstanceReflection = Activator.CreateInstance(typeof (B)); 

To:

 var bInstanceReflection = (B)Activator.CreateInstance(typeof (B)); 

So, now the compiler knows the type of bInstanceReflection and can call the correct implicit statement.

+1
source

All Articles