Fab*_*rie 9 c# linq ienumerable
我以为我知道一切,IEnumerable<T>
但我刚遇到一个我无法解释的案例.当我们调用.在一个linq方法上IEnumerable
,执行被推迟到对象被枚举,不是吗?
那么如何解释下面的示例:
public class CTest
{
public CTest(int amount)
{
Amount = amount;
}
public int Amount { get; set; }
public override string ToString()
{
return $"Amount:{Amount}";
}
public static IEnumerable<CTest> GenerateEnumerableTest()
{
var tab = new List<int> { 2, 5, 10, 12 };
return tab.Select(t => new CTest(t));
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止没什么不好的!但是下面的测试给了我一个意想不到的结果,虽然我的知识IEnumerable<T>
和.Where
linq方法:
[TestMethod]
public void TestCSharp()
{
var tab = CTest.GenerateEnumerableTest();
foreach (var item in tab.Where(i => i.Amount > 6))
{
item.Amount = item.Amount * 2;
}
foreach (var t in tab)
{
var s = t.ToString();
Debug.Print(s);
}
}
Run Code Online (Sandbox Code Playgroud)
选项卡中的任何项目都不会乘以2.输出将为:金额:2金额:5金额:10金额:12
有没有人可以解释为什么枚举选项卡后,我得到原始值.
当然,.ToList()
在调用GenerateEnumerableTest()
方法之后调用之后一切正常.
var tab = CTest.GenerateEnumerableTest();
Run Code Online (Sandbox Code Playgroud)
这tab
是一个LINQ查询,它生成CTest
从int
-values 初始化的实例,这些实例来自一个永远不会改变的整数数组.因此,每当您要求此查询时,您将获得"相同"实例(使用原始实例Amount
).
如果要"实现"此查询,可以使用ToList
然后更改它们.否则,您正在修改CTest
仅存在于第一个foreach
循环中的实例.第二个循环CTest
使用未修改的枚举其他实例Amount
.
因此查询包含如何获取项目的信息,您也可以直接调用该方法:
foreach (var item in CTest.GenerateEnumerableTest().Where(i => i.Amount > 6))
{
item.Amount = item.Amount * 2;
}
foreach (var t in CTest.GenerateEnumerableTest())
{
// now you don't expect them to be changed, do you?
}
Run Code Online (Sandbox Code Playgroud)
与许多 LINQ 操作一样,Select
它是惰性的并使用延迟执行,因此您的 lambda 表达式永远不会被执行,因为您正在调用Select
但从未使用结果。这就是为什么在.ToList()
调用GenerateEnumerableTest()
方法后调用后一切正常:
var tab = CTest.GenerateEnumerableTest().ToList();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
242 次 |
最近记录: |