为什么这个测试失败了?
private class TestClass
{
public string Property { get; set; }
}
[Test]
public void Test()
{
var testClasses = new[] { "a", "b", "c", "d" }
.Select(x => new TestClass());
foreach(var testClass in testClasses)
{
testClass.Property = "test";
}
foreach(var testClass in testClasses)
{
Assert.That(!string.IsNullOrEmpty(testClass.Property));
}
}
问题显然与Select语句中的延迟屈服有关,因为如果我在Select()方法之后添加.ToList()调用,则测试通过。
答案 0 :(得分:5)
由于LINQ的工作原理,您实际上正在创建 8 不同版本的TestClass
- 每foreach
一套4。基本上就像你有:
var testClasses = new[] { "a", "b", "c", "d" };
foreach(var testClass in testClasses.Select(x => new TestClass()))
{
testClass.Property = "test";
}
foreach(var testClass in testClasses.Select(x => new TestClass()))
{
Assert.That(!string.IsNullOrEmpty(testClass.Property));
}
第一组(丢弃)具有属性集。
通过在ToList()
末尾调用testClasses
,强制它存储并重复使用相同的4 TestClass
个实例,因此它会通过。
答案 1 :(得分:2)
每次迭代testClasses
变量时,都将运行.Select()
lambda表达式中的代码。在您的情况下,效果是不同的foreach循环获得TestClass
个对象的不同实例。
正如您所注意到的那样,在查询结尾处粘贴.ToList()
将确保仅执行一次。
答案 2 :(得分:0)
这是因为选择返回IEnumerable<T>
等LINQ扩展方法是懒惰的。试着更加渴望:
var testClasses = new[] { "a", "b", "c", "d" }
.Select(x => new TestClass())
.ToArray();