gpt4 book ai didi

c# - 令人惊讶的 linq 除了行为

转载 作者:行者123 更新时间:2023-11-30 19:35:25 25 4
gpt4 key购买 nike

我对以下 linq except 行为感到非常惊讶,有人可以解释为什么吗?我列出了我对 linq 工作原理的理解/假设。至少其中一个是错误的。

  1. 第一行定义了 list1,它在求值时会产生 Obj('a') 和 Obj('b')。
  2. 第二行定义了产生 Obj('b') 的 list2,它应该是从 list1 产生的同一个对象(引用相等)。
  3. 第三行定义了生成 Obj('a') 的 list3,它应该与从 list1 生成的对象相同(引用相等)。
public class Obj {
public string Name;
public Obj(string name)
{
this.Name = name;
}
}

class Program
{
public static void Main(string[] args)
{
var list1 = "a,b"
.Split(',')
.Select(x => new Obj(x));
var list2 = list1.Where(x => x.Name == "b");
var list3 = list1.Except(list2).ToList();
}
}

但显然,事实并非如此。在调试器中检查时,list3 包含 {Obj('a'), Obj('b')},并且这些对象不是 list1 所包含内容的引用。并且 Obj 构造函数被调用了 4 次。

linq Where 和 Excet 方法不应该只是将对象引用从一个 IEnumerable 复制到另一个 IEnumerable 吗?谁在创建对象副本?

最佳答案

问题是您的列表并不是真正的列表——它们是惰性求值序列。当这段代码执行时:

var list1 = "a,b"
.Split(',')
.Select(x => new Obj(x));

... Split 被立即调用,然后 Where 被调用以在该数组上设置延迟计算序列。如果您根本不遍历 list1,则不会创建 Obj 的实例。如果多次遍历 list1,每次都会获得新对象。

要使代码正常工作,您需要做的就是通过转换为列表(或者数组也可以)具体化查询:

var list1 = "a,b"
.Split(',')
.Select(x => new Obj(x))
.ToList();

或者,您可以覆盖 Obj 中的 EqualsGetHashCode,这样 Except 就会考虑不同但-适本地相等对象。

关于c# - 令人惊讶的 linq 除了行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57567298/

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