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

时间:2016-10-16 18:47:31

标签: c# casting

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

public class Foo { }

public class Bar
{
    public static implicit operator Foo(Bar bar) => new Foo();
}

现在我有一个方法,它希望一个对象作为一个参数投射到Foo

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

现在我这样称呼这个方法:

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

DoSomething(foo);
DoSomething(bar);

当来电DoSomething(foo)按预期工作时,来电DoSomething(bar)会引发InvalidCastException。为什么运行时不能在第二个方法调用中使用用户定义的类型转换运算符?

1 个答案:

答案 0 :(得分: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;
    }
}

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

static void DoSomething(object o)
{
    var foo = (Foo) (dynamic) o;
}