Let's say I have two classes where one is convertible into the other:
public class Foo { }
public class Bar
{
public static implicit operator Foo(Bar bar) => new Foo();
}
Now I have a method which expects an object as a parameter which it casts to Foo
.
public void DoSomething(object o)
{
var foo = (Foo)o;
/* Do something with foo here */
}
Now I call this method like so:
var bar = new Bar();
var foo = (Foo)bar;
DoSomething(foo);
DoSomething(bar);
While the call DoSomething(foo)
works as expected the call DoSomething(bar)
throws an InvalidCastException
. Why can't the runtime use the user-defined type conversion operator in the second method call?
Why can't the runtime use the user-defined type conversion operator in the second method call?
Because the compiler isn't executing at execution time... user-defined conversions are noticed by the compiler, not the runtime. The cast you've got will basically always fail unless the value is really a Foo
.
Now the way you can get round this is to use dynamic typing. If you make your method parameter have the dynamic
type, then the compiler will run (to some extent) at execution time, and find your conversion.
Example:
using System;
public class Foo { }
public class Bar
{
public static implicit operator Foo(Bar bar) => new Foo();
}
class Test
{
static void Main(string[] args)
{
var bar = new Bar();
var foo = (Foo)bar;
DoSomething(foo);
DoSomething(bar);
}
static void DoSomething(dynamic o)
{
var foo = (Foo) o;
}
}
Of course, it would be better if you could actually change the compile-time type of your parameter to Foo
instead... is there any reason you can't do that? Note that if you can't change the parameter type at all, you could always convert to dynamic
in the method:
static void DoSomething(object o)
{
var foo = (Foo) (dynamic) o;
}
See more on this question at Stackoverflow