【问题标题】:Why is a LINQ query called every time a variable is accessed?为什么每次访问变量时都会调用 LINQ 查询?
【发布时间】:2022-06-27 22:04:32
【问题描述】:

为什么Square() 在下面的代码中被再次调用?我想值正在重新计算,但为什么呢?我们之前得到了values,为什么又被调用了?为什么编译器会发出警告“Possible multiple enumeration”?

static IEnumerable<int> Square(IEnumerable<int> a)
{
    foreach(var r in a)
    {
        Console.WriteLine($"From Square {r * r}");
        yield return r * r;
    }
}
class Wrap
{
    private static int init = 0;
    public int Value
    {
        get { return ++init; }
    }
}

static void Main(string[] args)
{
    var w = new Wrap();
    var wraps = new Wrap[3];
    for(int i=0; i<wraps.Length; i++)
    {
        wraps[i] = w;
    }

    var values = wraps.Select(x => x.Value);
    var results = Square(values);
    int sum = 0;
    int count = 0;
    foreach(var r in results)
    {
        count++;
        sum += r;
    }
    Console.WriteLine("Count {0}", count);
    Console.WriteLine("Sum {0}", sum);

    Console.WriteLine("Count {0}", results.Count());
    Console.WriteLine("Sum {0}", results.Sum());
}

结果:

From Square 1
From Square 4
From Square 9
Count 3
Sum 14
From Square 16
From Square 25
From Square 36
Count 3
From Square 49
From Square 64
From Square 81
Sum 194

【问题讨论】:

  • 这就是yield 在 C# 中的工作原理。有很多话要说,但基本上,枚举的值或仅“按需”生成:每次调用代码“需要”一个新值时,都会创建一个新值(调用您的函数)。简单地将函数的结果分配给局部变量并不会这样做,但只有当您实际访问可枚举本身的“内容”时(“实现”它)。

标签: c# .net linq ienumerable


【解决方案1】:

Square(values) 返回一个IEnumerable,每次访问时都会对其进行迭代(调用)。

var results = Square(values).ToList();

将结果转换为List(),并将结果具体化为List()

.ToList() 的结果

From Square 1
From Square 4
From Square 9
Count 3
Sum 14
Count 3
Sum 14

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    相关资源
    最近更新 更多