我偶然发现 .NET 4.0 MS-C# 编译器的自动类型推导失败,我不得不“手动”指定类型。
这对我来说不是什么大问题,但足以让我好奇为什么编译器不能自动找到调用的正确类型。
我将调用减少到以下程序:
class Program
{
interface GenericInterface<T> { }
interface Covariant<out T> { }
static void Fn<T, U>(GenericInterface<T> t, U u)
where T : Covariant<U>
{
}
class Base { }
class Derived : Base { }
static void Main(string[] args)
{
Base b = null;
Derived d = null;
GenericInterface<Covariant<Base>> c = null;
Fn(c, b); // 1
Fn<Covariant<Base>, Base>(c, d); // 2
Fn(c, d); // 3
}
}
由于最后一次调用 Complex,代码无法编译,标记为“// 3”。
第一个调用简单直接 - 不涉及基类/子类。第二次调用只是“手动”指定所有参数。
我原以为编译器也会自动选择第二次调用中使用的参数来进行第三次调用。当然,第二个参数实际上是“Derived”,但这可以转换为“Base”,第一个参数需要 U 为“Base”类型。由于接口中的协变类型,where 子句应该仍然可以使用“Base”作为 U。
我不确切知道 C# 中泛型类型参数推导的规则,但我一直认为,它的工作原理有点像“如果参数只有一个可能的赋值,就使用这个。如果没有,拒绝编译。”
为什么编译器不自动检测类型?这是其中之一“如果编译器可以做到这一点,那么它也必须能够解决费马大定理” - 案例?:D