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

min*_*ill 9 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我不能说:

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

我得到一个错误说明'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).

Sri*_*vel 6

return "Hello".Left<string, int> (); // Compiles
Run Code Online (Sandbox Code Playgroud)

没有惊喜.您明确声明了类型参数,编译器很满意.

return "Hello".Left (); // Doesn't compile
Run Code Online (Sandbox Code Playgroud)

也不足为奇,编译器无法找出TR这种情况下的内容.TL可以推断因为TL作为参数传递leftTR不能.

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

  • `TR`*唯一可能的值,返回值是可接受的*是`int`.`TR`本身没有这个约束. (4认同)

fli*_*erg 5

我建议你看看部分7.5.2C#的规范.

7.5.2类型推断

在不指定类型参数的情况下调用泛型方法时, 类型推断过程会尝试推断调用的类型参数.类型推断的存在允许使用更方便的语法来调用泛型方法,并允许程序员避免指定冗余类型信息.

[...]

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

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

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