为什么在泛型方法中没有调用显式操作符
本文关键字:调用 操作符 泛型方法 为什么 | 更新日期: 2023-09-27 17:51:05
我把这个问题提炼成我能想到的最简单的代码示例。为什么显式操作符不从泛型方法调用?
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();
}
}
因为一个泛型方法有一个 IL集合,基于TResult
。它不会对每个调用者产生不同的IL。而泛型TResult
不有任何运算符。
还有:这里的运算符需要在object
和TResult
之间,并且不能定义包含object
的运算符。
例如:Cast<int>
、Cast<string>
和Cast<Guid>
都有完全相同的IL。
你可以用dynamic
:
return (TResult)(dynamic)o;
归根结底,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());
这样当你到达运行时它只是在执行另一个方法,一些运行时知道怎么做的事情。实际允许的运行时转换操作符是语言中包含的少数操作符(即从任何基类型到父类型,以及某些基本类型之间的转换操作符)。