Linq查询中出现意外结果,总是+1。

7
我有以下代码,但我期望得到不同的结果。
我期望得到以下结果:100, 110, 120, 200, 500
  using System;
  using System.Collections.Generic;
  using System.Linq;

  namespace ConsoleApplication11
  {
    public class Program
    {
      static void Main(string[] args)
      {
        var values = new List<int> { 100, 110, 120, 200 , 500 };

        //  In my mind the result shall be like (100,0) => 100 + 0 = 100 
        //  In my mind the result shall be like (110,0) => 110 + 0 = 110 etc. 
        var sumLinqFunction = new Func<int, int, int>((x, y) => x + y);
        var outputs = values.Select(sumLinqFunction);

        foreach (var o in outputs)
          Console.WriteLine(o);
      }
    }
  }

控制台输出(真实结果)

100
111
122
203
504

我现在想知道这个+1是从哪里来的?这与IT技术有关。

4
你为什么期望 y0 - SLaks
我本来想建议使用Enumerable.Aggregate,但我不知道实际需要的功能是什么。 - user7116
1
你的代码是为了解决什么问题而编写的? - Pavel Murygin
@PavelMurygin 我需要使用默认值0而不是索引来调用select! - Bassam Alugili
5个回答

17
这是因为你正在使用Select()方法的第二个参数只是输入集合中项目的索引。
编辑:
正如@user7116建议的那样,您可能希望在投影函数中简单地包括来自外部范围的值。
int y = 0;
var results = values.Select(x => x + y);

哦,真的吗?如果参数未定义,为什么选择不使用默认值0! - Bassam Alugili
如果参数未定义,我能否只使用0来强制选择或类似操作? - Bassam Alugili
2
@BassamAlugili:所以基本上你想在列表中添加0到所有的值。为什么不就让它保持原样呢?顺便说一句,“MAGIC OVERLOAD”非常有用。和for-loop一样有用。 - Tim Schmelter
4
@BassamAlugili这个过载中没有什么“神奇”的地方,它只是将项索引传递给投射函数。 - Efran Cobisi
1
@BassamAlugili:意外的默认值是神奇,重载只是重载。 - user7116
显示剩余2条评论

7
你的FuncsumLinqFunction,需要两个参数,将它们相加然后返回结果。
当你在Select语句中使用它时,应该这样写:
var outputs = values.Select((x, y) => x + y);

此处使用了重载的Select方法,该方法期望第二个参数为索引。

选择器的第一个参数表示要处理的元素。 选择器的第二个参数表示源序列中该元素的从零开始的索引。 如果元素以已知顺序排列,并且您想对特定索引处的元素执行某些操作,则此功能可能很有用。如果您想检索一个或多个元素的索引,则此功能也可能很有用。

因此,y0开始。 每次迭代,索引(y)移动到下一个元素,因此您会看到+1的增量。

为了进一步解释,您可以修改您的Func以显示xy的当前值,例如:

var sumLinqFunction = new Func<int, int, int>((x, y) =>
    {
        Console.WriteLine("x: {0} , y: {1}", x, y);
        return x + y;
    });
var outputs = values.Select(sumLinqFunction).ToList(); //iterate to get the results.

这将为您提供:
x: 100 , y: 0
x: 110 , y: 1
x: 120 , y: 2
x: 200 , y: 3
x: 500 , y: 4

针对您的评论:

我需要使用默认值0而不是索引来调用select!

那么,您可以简单地进行以下操作,而不是使用 Func

int y = 0;
var outputs = values.Select(r => r + y);

4

您正在使用错误的Select重载。

它只是将索引添加到当前值:

100 + 0
110 + 1
120 + 2
200 + 3
500 + 4

您不需要查询来获取预期的输出。
var values = new List<int> { 100, 110, 120, 200 , 500 };

foreach (var o in outputs)
      Console.WriteLine(o);

5
很可能原帖作者会在某个时候想要添加一些任意值,类似于 int y = 0; var results = values.Select(x => x + y); - user7116

4

请查看您调用的Select重载定义:

http://msdn.microsoft.com/zh-cn/library/bb534869.aspx

在这种情况下,您正在调用此重载:

public static IEnumerable<TResult> Select<TSource, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, int, TResult> selector
)

其中选择器为 (我强调)

应用于每个源元素的转换函数;函数的第二个参数表示源元素的索引

因此,您的选择器 lambda 返回当前数组索引处的数字加上数组索引,因此

(x, y) => x + y

(100,0) =>100+0

(110,1) =>110+1

(120,2) =>120+2

(200,3) =>200+3

(500,4) =>500+4


1

如果您想使用一些带有“default”参数值的函数:

    var values = new List<int> { 100, 110, 120, 200 , 500 };

    var sumLinqFunction = new Func<int, int, int>((x, y) => x + y);
    var outputs = values.Select(i => sumLinqFunction(i, 0));

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