我今天遇到了一个有趣的问题,我有两个方法,快速浏览一下,它们都做了同样的事情。即返回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?
注意:我想要解释一下为什么会发生这种情况,以及两者之间的区别。不知道如何修复第二个断言,因为我知道如果我向List2添加一个ToList调用,它就会工作。
发布于 2009-06-24 04:24:02
这绝对不是一回事。
第一个方法在你调用它的时候构建并返回一个列表,如果你想要的话,你可以把它转换回list和list-y元素,包括添加或删除项,一旦你把结果放入一个变量中,你就可以对这一组结果进行操作。调用该函数会产生另一组结果,但重用单个调用的结果会对相同的对象起作用。
第二个是构建一个IEnumerable。您可以枚举它,但如果不先对其调用.ToList(),就不能将其视为列表。实际上,在实际迭代该方法之前,调用该方法不会做任何事情。考虑一下:
var fooList = Data.List2().Where(f => f.ID > 1);
// NO foo objects have been created yet.
foreach (var foo in fooList)
{
// a new Foo object is created, but NOT until it's actually used here
Console.WriteLine(foo.Enabled.ToString());
}注意,上面的代码将创建第一个(未使用的) Foo实例,但直到进入foreach循环。因此,直到被调用时,这些项才会被实际创建。但这意味着每次调用它们时,您都在构建一组新的项。
https://stackoverflow.com/questions/1036272
复制相似问题