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

本文关键字:转换 异常 无效 对象 参数传递 | 更新日期: 2023-09-27 18:13:26

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

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。为什么运行时不能在第二个方法调用中使用用户定义的类型转换操作符?

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

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

因为编译器在执行时没有执行…用户定义的转换由编译器注意,而不是运行时。你得到的强制转换基本上总是会失败,除非值真的是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;
}