【发布时间】:2019-08-20 14:18:12
【问题描述】:
除了行为之外,我对以下 linq 感到非常惊讶,谁能解释为什么?我列出了我对 linq 如何工作的理解/假设。其中至少有一个是错误的。
- 第一行定义了 list1,它在计算时会产生 Obj('a') 和 Obj('b')。
- 第二行定义了产生 Obj('b') 的 list2,它应该与从 list1 产生的对象(引用相等)相同。
- 第三行定义了产生 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?谁在创建对象副本?
【问题讨论】:
-
这种行为对我来说似乎是正确的。请记住,LINQ 实际上是一种视图,并且在您要求之前不会实现任何东西。
-
@John 这让我很困惑。如果它们只是视图,则 list1、ilst2 和 list3 应该只是对相同 2 个对象的不同视图。但是在调试时,一共创建了 4 个对象。
-
它们都是
"a,b".Split(',')产生的数组的视图,而不是list1的视图。 -
我打算将其纳入答案,但乔恩击败了我。这是一个example - 它表明在实现结果之前实际上没有任何评估。还有another example,我们在做其他事情之前实现
list1。 -
@John 谢谢你们。这不是他第一次帮助我。你纠正了我深信自己理解的误解之一。