gpt4 book ai didi

c# - 为什么 LINQ 以不同的方式对待执行 "same"事情的两种方法?

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

我今天遇到了一个有趣的问题,我有两种方法,乍一看,它们都做同样的事情。即返回 Foo 对象的 IEnumerable。

我在下面将它们定义为 List1 和 List2:

public class Foo
{
public int ID { get; set; }
public bool Enabled { get; set;}
}

public static class Data
{
public static IEnumerable<Foo> List1
{
get
{
return new List<Foo>
{
new Foo {ID = 1, Enabled = true},
new Foo {ID = 2, Enabled = true},
new Foo {ID = 3, Enabled = true}
};
}
}

public static IEnumerable<Foo> List2
{
get
{
yield return new Foo {ID = 1, Enabled = true};
yield return new Foo {ID = 2, Enabled = true};
yield return new Foo {ID = 3, Enabled = true};
}
}
}

现在考虑以下测试:

IEnumerable<Foo> listOne = Data.List1;
listOne.Where(item => item.ID.Equals(2)).First().Enabled = false;
Assert.AreEqual(false, listOne.ElementAt(1).Enabled);
Assert.AreEqual(false, listOne.ToList()[1].Enabled);

IEnumerable<Foo> listTwo = Data.List2;
listTwo.Where(item => item.ID.Equals(2)).First().Enabled = false;
Assert.AreEqual(false, listTwo.ElementAt(1).Enabled);
Assert.AreEqual(false, listTwo.ToList()[1].Enabled);

这两种方法似乎在做“相同”的事情。

为什么测试代码中的第二个断言会失败?
为什么 listTwo 的第二个“Foo”项在 listOne 中时没有设置为 false?

注意:我正在解释为什么允许这种情况发生以及两者之间的区别。不是如何修复第二个断言,因为我知道如果我将 ToList 调用添加到 List2 它将起作用。

最佳答案

第一个代码块构建项目一次并返回包含项目的列表。

每次遍历 IEnumerable 时,第二个代码块都会构建这些项目。

这意味着第一 block 的第二行和第三行对同一个对象实例进行操作。第二个 block 的第二行和第三行对 Foo 的不同实例进行操作(在您迭代时创建新实例)。

查看此内容的最佳方法是在方法中设置断点并在调试器下运行此代码。第一个版本只会命一次断点。第二个版本将命中它两次,一次是在 .Where() 调用期间,一次是在 .ElementAt 调用期间。 (编辑:使用修改后的代码,它还会在 ToList() 调用期间第三次命中断点。)

这里要记住的是,迭代器方法(即它使用 yield return)每次都会在枚举器迭代时运行,而不仅仅是在构造初始返回值时。

关于c# - 为什么 LINQ 以不同的方式对待执行 "same"事情的两种方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1036272/

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