C# Linq and lambda

本文关键字:lambda and Linq | 更新日期: 2023-09-27 17:55:09

How Do Select(int.解析)在这样的 Linq 表达式中工作?

"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

当允许省略 lambda 时,例如 (x => ....(十))

C# Linq and lambda

Console.WriteLine以及int.Parse都是所谓的方法组。方法组。因为这些方法的各种重载。它可以是一种方法,也可以是多种方法。

如果编译器可以推断出组的哪个方法是指方法组,则可以将方法组转换为委托。例如,方法组int.Parse可以是int.Parse(string)是否需要Func<string, int>的委托。

这在您的第一个示例中有效。 Select需要Func<T, T2>,并且您的T已设置为类型 string 。但是,它不适用于您的第二个示例。因为虽然Console.WriteLine是一个方法组,但该组中没有一个方法对应于所需的Func<T, T2>因为组中所有方法的返回类型都是void

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。

Select 是一个投影语句,它将您的对象转换为您在Select中指定的新对象。你需要循环并执行 WriteLine:

"1,2,3,4,5".Split(',').ToList().ForEach(x=> {  Console.WriteLine(x); });

选择需要参数Func<char, T>Console.WriteLine不匹配。

几乎所有的 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

当方法签名与 LinQ 预期相同时,允许这样做。

在第一种情况下,Select的预期签名是一个具有一个string参数和返回值int (或简称Func<string, int>)的方法,并且int.Parse方法具有相同的签名,这就是它工作的原因;

而在第二种情况下,Console.WriteLine的签名是一个string参数的方法,没有返回值(或特殊类型void的返回值)(或简称Action<string>),因此Select期望的签名和Console.WriteLine的签名不匹配。