我把这个问题提炼成我能想到的最简单的代码示例。为什么不从泛型方法调用显式运算符?
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();
}
}
答案 0 :(得分:9)
因为通用方法具有一个 IL集,基于TResult
。它不会对每个呼叫者执行不同的IL。通用TResult
不有任何运算符。
此外:此处的运营商需要介于object
和TResult
之间,无法定义涉及object
的运算符。
例如:Cast<int>
和Cast<string>
以及Cast<Guid>
都具有完全相同的IL。
您可以使用dynamic
作弊:
return (TResult)(dynamic)o;
答案 1 :(得分:2)
归结为implicit
和explicit
运算符不是 true 转换运算符;他们完全编译时间语法糖。编译代码后,转换运算符的任何内容都不存在。
当编译器看到:
B b = (B) new A();
它说,“从A
到B
是否存在任何原生转化(隐式或显式)?” (例如,如果A
扩展B
,或者为double
到int
(隐式)等少数特殊的套装语言转换之一就是这种情况,或者int
至double
(明确)。)
如果没有,它会查找用户定义的转化运算符(它只在A
和B
的定义中查找,它不会在C
的定义中查找例如,从A
到B
的隐式转换。如果找到一个,则它将该运算符作为静态方法调用注入,因此代码最终看起来像:
B b = B.SomeAutogneratedName(new A());
那样,当你进入运行时它只是执行另一个方法,运行时知道该怎么做。唯一允许的实际运行时转换运算符是少数语言(即从任何基类型到父类型,以及某些基元类型之间)。