5

我已经将这个问题提炼成我能想到的最简单的代码示例。为什么不从泛型方法调用显式运算符?

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        B b = (B)a; // works as expected
        b = Cast<B>(a);
    }

    static TResult Cast<TResult>(object o)
    {
        return (TResult)o; // throws Invalid Cast Exception
    }
}

class A
{
}

class B
{
    public static explicit operator B(A a)
    {
        return new B();
    }
}
4

2 回答 2

10

因为泛型方法有组 IL,基于TResult. 它不会对每个调用者执行不同的 IL。并且泛型TResult 没有任何运算符。

另外:这里的运算符需要介于objectand之间TResult,并且您不能定义涉及 . 的运算符object

例如:Cast<int>and Cast<string>andCast<Guid>都具有完全相同的 IL。

你可以作弊dynamic

return (TResult)(dynamic)o;
于 2013-01-09T20:53:04.203 回答
2

归结为implicitandexplicit运算符不是真正的转换运算符。它们完全是编译时语法糖。编译代码后,不会保留任何有关转换运算符的信息。

当编译器看到:

B b = (B) new A();

A它说,“是否存在从 a到 a 的任何本机转换(隐式或显式)B?” A(例如,如果是扩展的,就会出现这种情况B),或者是为数不多的特殊语言转换之一,例如doubleto int(implicit) 或intto double(explicit)。)

如果不是,则查找用户定义的转换运算符(例如,它只查找 and 的定义,A而不B查找from和 toC的隐式转换)。如果它找到一个,那么它将该运算符作为静态方法调用注入,因此代码最终看起来像:AB

B b = B.SomeAutogneratedName(new A());

这样,当你进入运行时,它只是在执行另一个方法,运行时知道该怎么做。唯一允许的实际运行时转换运算符是语言中的少数几个(即从任何基本类型到父类型,以及某些原始类型之间)。

于 2013-01-09T21:19:45.533 回答