作为对象参数传递时,无效的强制转换异常

Tho*_*ser 2 c# casting

假设我有两个类,其中一个可以转换为另一个:

public class Foo { }

public class Bar
{
    public static implicit operator Foo(Bar bar) => new Foo();
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个方法,它期望一个对象作为它所投射的参数Foo.

public void DoSomething(object o)
{
    var foo = (Foo)o;
   /* Do something with foo here */
}
Run Code Online (Sandbox Code Playgroud)

现在我这样调用这个方法:

var bar = new Bar();
var foo = (Foo)bar;

DoSomething(foo);
DoSomething(bar);
Run Code Online (Sandbox Code Playgroud)

当呼叫DoSomething(foo)按预期工作时,呼叫DoSomething(bar)会抛出一个InvalidCastException.为什么运行时不能在第二个方法调用中使用用户定义的类型转换运算符?

Jon*_*eet 7

为什么运行时不能在第二个方法调用中使用用户定义的类型转换运算符?

因为编译器没有在执行时执行... 编译器会注意到用户定义的转换,而不是运行时.你得到的演员阵容基本上总会失败,除非价值真的是一个Foo.

现在你可以绕过这个方法就是使用动态类型.如果使方法参数具有dynamic类型,则编译器在执行时运行(在某种程度上),并找到您的转换.

例:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果你真的可以改变你的参数的编译时类型,那会更好Foo......你有什么理由不能这样做吗?请注意,如果您根本无法更改参数类型,则始终可以dynamic在方法中转换为:

static void DoSomething(object o)
{
    var foo = (Foo) (dynamic) o;
}
Run Code Online (Sandbox Code Playgroud)