I was suprised when found that the following code throws 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);
}
}
Could anyone tell me why? I don't really understand what happened
You shouldn't be surprised - custom operators don't override anything, they overload - so they're picked at compile time, not execution time.
When we remove implicit typing from the code, it makes it a bit clearer:
object bInstanceReflection = Activator.CreateInstance(typeof (B));
Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
A aInstanceReflection = (A) bInstanceReflection;
Now it's reasonably clear that in the final line, (A)
is just a cast from object
which performs the normal reference conversion. No user-defined conversions will be applied at all.
If you're using .NET 4, you can use dynamic typing to get it to work:
// Note the change of type
dynamic bInstanceReflection = Activator.CreateInstance(typeof (B));
Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
A aInstanceReflection = (A) bInstanceReflection;
Now the conversion is being applied on a dynamic value, which means the choice of what conversion to use is deferred until execution time - at which point it will use your custom operator.
You've created a B
. And then cast it to an A
.
Despite having similar layouts, B has no relationship to A. Static operators are applied by the compiler, but not at runtime via cast. Although the C# syntax is the same, they are very different when dealing with reflection.
This is the normal, expected behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With