Thomas Schremser Thomas Schremser - 1 month ago 5
C# Question

Invalid cast exception when passed as object parameter

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?

Answer

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;
}
Comments