有人可以解释这个Linq查询吗?

时间:2009-10-01 20:56:12

标签: c# linq

我从msdns 101 linq示例中得到了这个linq示例:

public void Linq12() {
    int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

  var numsInPlace = numbers.Select((num, index) => new {Num = num, InPlace = (num ==     
  index)});

    Console.WriteLine("Number: In-place?");
    foreach (var n in numsInPlace) {
        Console.WriteLine("{0}: {1}", n.Num, n.InPlace);
    }
}

以下是我的问题:

  1. 什么是(num,index)部分?这些可以被称为a,b之类的东西,可以有我想要的吗?

  2. 编译器如何确定匿名类型的类型?

  3. 什么是=>用于?

  4. 必须始终至少有一个参数。例如,在下面的linq查询中是一个参数或者这个选择与另一个不同(Select(num,index))

    int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
    
    var numsPlusOne =
        from n in numbers
        select n + 1;
    }
    

5 个答案:

答案 0 :(得分:4)

1)这些参数传递给Enumerable.Select重叠使用的Func<TSource, Int32, TResult>

正在发生的事情是编译器自动创建一个lambda,它将可枚举的“{<T>”及其索引传递给您正在生成的函数。您将其命名为“num”和“index”,“num”是数组中的整数,“index”是数组的索引。您可以将它们命名为任何名称,但它们必须存在于Select方法使用的Func中(在这种情况下,总会有两个,第二个将是int)。

2)编译器为您创建一个新类型。匿名类型就是这样 - 一个匿名类型,它使用与您在其中分配的类型相对应的属性生成,在本例中为int(Num)和bool(InPlace)。类型取决于所设置的内容。

3)这是Lambda Operator。它允许您创建一个lambda表达式,这是一个内联定义的函数,没有名称返回单个值。

4)在你的第二种情况下,LINQ调用Select的重载,它需要一个Func<TSource,TResult>,所以你只有一个参数。 Enumerable.Select有两个版本。

答案 1 :(得分:2)

  

这些可以被称为任何东西吗?

  

可以有多少我想要的吗?

没有。这是一个函数的签名,它必须匹配IEnumerable<T>.Select()重载的一个选择器参数。来自文档:

  

selector的第一个参数表示要处理的元素。 selector的第二个参数表示源序列中该元素的从零开始的索引。

  

编译器如何确定匿名类型的类型?

它在现场组成了一种新型。好吧,有点。编译器组成一个新类型,即使在那里它偶尔也会重新使用组合类型。

  

什么是=&gt;用于?

这是lambda运算符(也称为“wang”运算符。真的。)。它告诉编译器你正在构建一个lambda表达式(基本上是一个内联函数)。

  

必须始终至少有一个参数。

在这种情况下,是的。您必须创建一个表达式,该表达式与调用Select()方法的selector参数的预期类型相匹配。在其他情况下,没有。你当然可以这样做:

Func<string> x = () => string.Empty;
  

是一个参数或者这个选择与另一个

不同

编译器将翻译选择的代码,以使用与select扩展方法相同的IL。但是,它是一个不同的选择,因为它使用不同的重载。

答案 2 :(得分:1)

使用

(num,index),因为lambda表达式有两个参数。 你应该能够调用这些你想要的东西,但是将第二个“索引”称为它所代表的内容的提醒是很有用的。 对于Select,我相信你只能使用一个或两个参数。

我担心我无法解决你的第二个问题。

编辑: 关于您的新问题,“=&gt;”只是lambda表达式的语法。此左侧的表达式表示参数,右侧的表达式表示函数的主体。

据我所知,这是:

var numsPlusOne =
 from n in numbers
 select n + 1;

与此相同:

var numsPlusOne = numbers.Select(n => n + 1);

区别仅在于语法(如何编写。)

答案 3 :(得分:1)

  1. 是的,它们可以被称为a或b;它们是代表中使用的参数。

  2. 编译器只生成一个匿名类型;那是类型。

答案 4 :(得分:1)

1
(num, index)是lamda表达式中的参数。它采取以下形式:

(parameters) => expression

如果只有一个参数,则可以省略括号:

parameter => expression

您可以将任何您喜欢的参数命名为与范围内的其他变量不冲突的参数。

lambda表达式中可以有任意数量的参数(甚至为零),但是当您在调用方法时使用它时,它必须匹配方法所期望的委托的签名。

2
编译器不确定匿名类的类型,它会创建一个包含所设置属性的新匿名类。