为什么C#编译器不能推断返回值的类型参数?

时间:2014-10-10 06:51:54

标签: c# generics type-inference

我有这段代码(为了清晰起见,最小化):

interface IEither<out TL, out TR> {
}

class Left<TL, TR> : IEither<TL, TR> {
    public Left(TL value) { }
}

static class Either {
    public static IEither<TL, TR> Left<TL, TR> (this TL left) {
        return new Left<TL, TR> (left);
    }
}

为什么我不能说:

static class Foo
{
    public static IEither<string, int> Bar ()
    {
        //return "Hello".Left (); // Doesn't compile
        return "Hello".Left<string, int> (); // Compiles
    }
}

我收到一条错误,指出'string' does not contain a definition for 'Left' and no extension method 'Left' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) (CS1061)

3 个答案:

答案 0 :(得分:6)

return "Hello".Left<string, int> (); // Compiles

毫不奇怪。您明确声明了类型参数,编译器很满意。

return "Hello".Left (); // Doesn't compile

也不奇怪,在这种情况下,编译器无法找出TR的内容。可以推断TL,因为TL作为参数left传递,但TR不能传递。{/ p>

C#编译器没有假设您的意思,如果意图不明确,它将引发编译器错误。如果编译器认为您可能做错了什么,它会给编译器警告。

答案 1 :(得分:5)

我建议您查看C#规范中的 7.5.2 部分。

  

7.5.2类型推断

     

当调用泛型方法而不指定类型参数时,a    类型推断进程尝试推断调用的类型参数。    类型推断的存在允许更方便的语法    用于调用泛型方法,并允许程序员避免    指定冗余类型信息。

     

[...]

     

类型推断作为方法调用(第7.6.5.1节)的绑定时处理的一部分发生,并且发生在调用的重载决策步骤之前[...]

即解决方案在任何类型的重载解决方案完成之前发生,问题是按照你说的方式推断类型甚至没有尝试过,坦白说也不总是可行。

泛型类型参数的类型解析只能通过调用中的参数完成!在你的例子中只有一个string!它不能从参数推断int,只能推断在泛型类型解析时未解析的调用上下文。

答案 2 :(得分:1)

免责声明:这个答案涉及猜测。

有关TR的信息在于,它被用作return的子表达式,而IEither<Foo, Bar>可以与TR匹配,以生成Barreturn的信息。

但是存在问题。当编译器具有抽象语法树时,通过逐渐移向树的叶子,更容易从根开始并推断表达式类型,解决重载等。这是最容易做的事情,也是经常做的事情。

您的场景要求编译器完全向后工作 - 从方法调用到构造函数调用<string, int>的子表达式,然后查阅当前方法的声明(并找出正确的组合是var,因为任何其他人都无法编译)。乍一看,这很难实现。

但是在C#中有一些优先权:你可以创建一个(更高阶)函数,只返回一个lambda,类型推断根据声明工作。在声明局部变量时,这种事情也适用于lambdas(你不能将它们分配给{{1}}并要求编译器推断出后续用法中的参数类型。)

那么,为什么他们没有为你所描述的情况实施它,考虑到他们是用lambdas做的呢?

  1. 他们用lambdas来做这件事:lambda表达式的全部意义在于它们看起来不是什么大不了的事 - 它们应该尽可能地易于编写(按顺序排列)快速表达过滤标准,排序标准等。这很有价值。
  2. 即使这种事情与lambdas有关,但它还远非完美 - 事实上,它可能会不时地以非常奇怪的方式表现。因此,设计师可能会将其看作是一种必要的邪恶,不应该扩展到其他语言。
  3. 您的案例很少见,而且解决方法很简单。
  4. 可能仅仅是&#34;没有人实施但是&#34;