gpt4 book ai didi

c# - Linq 的执行顺序是这个问题的原因吗?

转载 作者:太空宇宙 更新时间:2023-11-03 20:21:05 26 4
gpt4 key购买 nike

我有这个函数来重复一个序列:

public static List<T> Repeat<T>(this IEnumerable<T> lst, int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException("count");

var ret = Enumerable.Empty<T>();

for (var i = 0; i < count; i++)
ret = ret.Concat(lst);

return ret.ToList();
}

现在如果我这样做:

var d = Enumerable.Range(1, 100);
var f = d.Select(t => new Person()).Repeat(10);
int i = f.Distinct().Count();

我希望 i 为 100,但它给了我 1000!我的问题严格来说是为什么会这样? Linq 难道不应该足够聪明,知道它是我需要与变量 ret 连接的第一个选定的 100 个人吗?我感觉这里 Concatret.ToList() 执行时与 Select 一起使用时被优先考虑..

编辑:

如果我这样做,我会得到预期的正确结果:

var f = d.Select(t => new Person()).ToList().Repeat(10); 
int i = f.Distinct().Count(); //prints 100

再次编辑:

我没有覆盖Equals。我只是想获得 100 个独特的人(当然是引用)。我的问题是有人可以向我解释为什么 Linq 不先进行选择操作然后进行连接(当然是在执行时)吗?

最佳答案

问题是,除非您调用 ToList,否则 d.Select(t => new Person()) 会在每次 Repeat 时重新枚举 遍历列表,创建重复的 Person。该技术被称为 deferred execution .

通常,LINQ 不会假设每次枚举一个序列时都会得到相同的序列,甚至是相同长度的序列。如果这种效果不理想,您始终可以通过立即调用 ToList 来“具体化”您的 Repeat 方法中的序列,如下所示:

public static List<T> Repeat<T>(this IEnumerable<T> lstEnum, int count) {
if (count < 0)
throw new ArgumentOutOfRangeException("count");

var lst = lstEnum.ToList(); // Enumerate only once
var ret = Enumerable.Empty<T>();

for (var i = 0; i < count; i++)
ret = ret.Concat(lst);

return ret.ToList();
}

关于c# - Linq 的执行顺序是这个问题的原因吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13500641/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com