1

我偶然发现 .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

4

1 回答 1

2

由于接口中的协变类型,where 子句应该仍然可以使用“Base”作为 U。

我认为这是你出错的地方。编译器不认为泛型约束是方法签名的一部分

所以我认为在你的第三种情况下可能发生的是编译器正在推断T = Covariant<Base>U = Derived. 然后它继续检查 T. 上的通用约束 Covariant<Base>没有实现Covariant<Derived>,因此约束不满足并且编译失败。

于 2013-12-04T15:10:13.013 回答