简单的Linq表达式无法编译

10
拥有这些基本定义
bool MyFunc(string input)
{
    return false;
}
var strings = new[] {"aaa", "123"};

我想知道为什么这个代码无法编译:
var b = strings.Select(MyFunc);

但是这个可以:
var c = strings.Select(elem => MyFunc(elem));

错误信息为"无法从使用中推断方法'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)'的类型参数。"

Resharper错误提示称它在以下两个类型之间感到困惑:

Select(this IEnumerable<string>, Func<string, TResult>)

并且。
Select(this IEnumerable<string>, Func<string, int, TResult>)

...但是MyFunc的签名很明确——它只需要一个(字符串)参数。

有人能在这里解释一下吗?

2个回答

14

泛型类型推断在C# 3和C# 4编译器之间的实现略有变化。以下是一个简短但完整的示例程序:

using System;
using System.Linq;

class Test
{
    static void Main()
    {
        string[] strings = { "a", "b" };
        var results = strings.Select(MyFunc);
    }

    static bool MyFunc(string input)
    {
        return true;
    }
}

这段代码可以在.NET 4的C#编译器中编译,但无法在.NET 3.5的编译器中编译。

我认为称其为错误修复是合理的,因为我认为这不是规范变更。

如果你必须使用.NET 3.5的编译器,你可以添加一个强制转换来澄清:

var results = strings.Select((Func<string,bool>) MyFunc);

或者

var results = strings.Select(new Func<string,bool>(MyFunc));

或者你可以显式地指定类型参数:

var results = strings.Select<string, bool>(MyFunc);

所以我认为编译器会自动解决问题并不是不合理的想法... - Cristian Diaconescu
@Cristi:不,尽管尝试从规范中确定它应该如何工作是棘手的。我认为规范中的类型推断部分上面写着“这里有龙”。 - Jon Skeet
我们决定改变行为,当发现无法将更改纳入C# 3时,我们将其放入了C# 4中。 - Eric Lippert
(而且,我和Mads可能会再次重写类型推断规范,因为目前的规范在命名/可选参数方面是不正确的。我们将尽力使其更易于理解。) - Eric Lippert
1
@Eric:如果你需要测试新规范的测试人员,我很乐意提供帮助 :) - Jon Skeet
显示剩余3条评论

6

Jon一如既往地正确。以下是一些额外信息:

这是我在2007年撰写的博客文章,在其中描述了你遇到的问题:

http://blogs.msdn.com/b/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx

基于那篇文章的反馈,我们决定修复此问题,但由于排期原因无法将修复程序放入C# 3中。

几个月后,我宣布该修复程序将加入C# 4,而不是C# 3服务包中:

http://blogs.msdn.com/b/ericlippert/archive/2008/05/28/method-type-inference-changes-part-zero.aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接