为什么在通用方法中不调用显式运算符

时间:2013-01-09 20:49:48

标签: c# generics

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

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();
    }
}

2 个答案:

答案 0 :(得分:9)

因为通用方法具有一个 IL集,基于TResult。它不会对每个呼叫者执行不同的IL。通用TResult 有任何运算符。

此外:此处的运营商需要介于objectTResult之间,无法定义涉及object运算符。

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

您可以使用dynamic作弊:

return (TResult)(dynamic)o;

答案 1 :(得分:2)

归结为implicitexplicit运算符不是 true 转换运算符;他们完全编译时间语法糖。编译代码后,转换运算符的任何内容都不存在。

当编译器看到:

B b = (B) new A();

它说,“从AB是否存在任何原生转化(隐式或显式)?” (例如,如果A扩展B,或者为doubleint(隐式)等少数特殊的套装语言转换之一就是这种情况,或者intdouble(明确)。)

如果没有,它会查找用户定义的转化运算符(它只在AB的定义中查找,它不会在C的定义中查找例如,从AB的隐式转换。如果找到一个,则它将该运算符作为静态方法调用注入,因此代码最终看起来像:

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

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