C#Linq和lambda
如何选择(int.Parse)在这样的Linq表达式中工作?C#Linq和lambda
"1,2,3,4,5".Split(',').Select(int.Parse).ToList(); //ok
"1,2,3,4,5".Split(',').Select(x => int.Parse(x)).ToList(); //ok
为什么Console.Writeline的例子返回编译错误?
"1,2,3,4,5".Split(',').Select(Console.WriteLine).ToList(); //error
"1,2,3,4,5".Split(',').Select(x => Console.WriteLine(x)).ToList(); //ok
当它被允许省略拉姆达像(X => ....(X))
选择是一个预测的语句,它把你的对象到您内指定一个新的对象Select
。你需要循环和执行的WriteLine:
"1,2,3,4,5".Split(',').ToList().ForEach(x=> { Console.WriteLine(x); });
选择需要一个参数Func<char, T>
,Console.WriteLine
不匹配。
当方法签名与LinQ期望的相同时,允许使用它。
在你的第一种情况,Select
的预期的签名与int
(或简称Func<string, int>
)一个string
参数和返回值和int.Parse
方法的方法相同签名,这就是为什么它的工作;
而在第二种情况下,Console.WriteLine
的签名是与一个string
参数和返回值(或特殊类型void
的返回值)(或简称Action<string>
),因此签名的方法,其Select
期望和Console.WriteLine
的签名不匹配。
这是'功能
的Select
签名看起来有点像这样:
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector);
所以对于selector
的方法(或lambda)与签名
TResult Method(string s);
预期。 Console.WriteLine()
是退货类型void
这是不是有效类型对于TResult
。所以实际上两条线:
"1,2,3,4,5".Split(',').Select(Console.WriteLine).ToList();
"1,2,3,4,5".Split(',').Select(x => Console.WriteLine(x)).ToList();
不进行编译。你确定你真的编译了第二行吗?我的编译器为两行提出了错误CS0411。
Console.WriteLine
以及int.Parse
都是所谓的方法组。一组方法。由于这些方法的各种重载。它可以是一种方法,也可以是多种方法。
如果编译器可以推断出该组的哪一种方法,方法组可以转换为委托。例如,如果预计有Func<string, int>
,方法组int.Parse
可以是int.Parse(string)
的代表。
这在你的第一个例子中有效。 Select
预计Func<T, T2>
和您的T
已被设置为类型string
。但是,它不会而是与您的第二个示例一起使用。因为虽然Console.WriteLine
是一个方法组,但该组中的单个方法并不对应于所需的Func<T, T2>
,因为该组中的方法的返回类型全部为为void
。
几乎所有的LINQ扩展接受返回值的函数。 Console.WriteLine
不返回任何内容,因此它不能用作参数。
"12345".Select(x => { Console.WriteLine(x); return x; }).ToList(); // this will work
"12345".Select(int.TryParse).ToList(); // this will NOT work because TryParse needs more than one parameter
"12345".ToList().ForEach(Console.WriteLine); // this will work because .ForEach accepts a method that does not return anything (void)
"12345".ToList().ForEach(int.Parse); // this will NOT work
第4行不应编译为 – fubo
第3个和第4个正试图产生一个List。你认为那个列表可以是*列表*吗? – AakashM
非正式地,'选择'期望它的参数是一个函数,它需要'T's并生成'U's。通常情况下会发生这种情况,例如,如果您传递'int.Parse',编译器会推断出'T = string'和'U = int'。然而,'T'和'U'必须是类型,它们不能是'空白'。 'Console.WriteLine'返回不是有效类型的'void',所以第3行和第4行不会编译(两者)。 –
CompuChip