为什么这个代码不能在VS2010中用.NET 4.0编译?

wan*_*gzq 9 .net c# linq visual-studio-2010 visual-studio-2012

不知何故,以下代码无法在VS2010中编译,而是在VS2012中编译而不进行更改.VS2010中有问题的一行是

names.Select(foo.GetName)
Run Code Online (Sandbox Code Playgroud)

错误CS1928:'string []'不包含'Select'的定义和最佳扩展方法重载'System.Linq.Enumerable.Select <TSource,TResult>(System.Collections.Generic.IEnumerable <TSource>,System. Func <TSource,TResult>)'有一些无效的参数.

using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            var foo = new Foo();
            var names = new[] {"Hello"};
            Console.WriteLine(string.Join(", ", names.Select(foo.GetName)));
        }
    }

    public class Foo
    {
    }

    static class Extensions
    {
        public static string GetName(this Foo foo, string name)
        {
            return name;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Til*_*lak 3

更新答案

我检查过该代码片段names.Select(foo.GetName)在 VS 2012 中编译,但在 VS2010 上不编译。

我不知道原因(确切地说是 C# 5.0 或 .NET 4.5 或新 API 中的新功能)使它成为可能。

但出现以下错误

The type arguments for method 'System.Linq.Enumerable.Select<TSource,TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TResult>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Run Code Online (Sandbox Code Playgroud)

似乎Enumerable.Select无法推断 的参数和返回类型foo.GetName

指定类型,代码将编译。

以下是3个选项

1. 投射到Func<string,string>

string.Join(", ", names.Select<string,string>(foo.GetName).ToArray())
Run Code Online (Sandbox Code Playgroud)

2. Select在子句 中将类型指定为通用参数

string.Join(", ", names.Select((Func<string,string>)foo.GetName).ToArray())
Run Code Online (Sandbox Code Playgroud)

3. 在匿名委托中显式调用函数。

 Console.WriteLine(string.Join(", ", names.Select( name => foo.GetName(name))))
Run Code Online (Sandbox Code Playgroud)

但正如 Jon Skeet 在评论中指出的那样,上面将通过创建一个新方法来添加另一个函数调用。

原答案

为什么这段代码不能在 .NET 4.0 的 VS2010 中编译?

您没有将参数传递给名称。您正在传递方法名称来代替Func<T1,T2>.


下面将编译

Console.WriteLine(string.Join(", ", names.Select( name => foo.GetName(name))))
Run Code Online (Sandbox Code Playgroud)

  • 嗯,不完全是。它们不是等效的代码,完全不同 - 您的代码将创建一个仅委托给 GetName 的新方法,然后使用该方法创建一个委托...而原始代码将创建一个直接引用 GetName 的委托。 (3认同)