在工作中,我遇到了一个奇怪的问题,本来希望终止的循环实际上无限期地在运行。
我将问题追溯到使用Select。有趣的是,当我在后面添加一个权利时,循环按预期终止。我将其简化为一个小例子。.ToList()Select
class WrappedBool
{
public WrappedBool(bool inner)
{
InnerBool = inner;
}
public bool InnerBool { get; set; } = false;
}
// remove .ToList() here and the following loop will go infinite
IEnumerable<WrappedBool> enumerable =
new List<bool>() { false, true, false }
.Select(b => new WrappedBool(b))
.ToList();
while (enumerable.Any(wb => !wb.InnerBool))
{
WrappedBool firstFalse = enumerable.Where(wb => !wb.InnerBool).First();
firstFalse.InnerBool = true;
}
Run Code Online (Sandbox Code Playgroud)
尽管我不必处理代码不再终止的问题,但我仍然想知道这种行为最初来自何处。
好吧,没有实现(.ToList())enumerable只是一个查询
IEnumerable<WrappedBool> enumerable =
new List<bool>() { false, true, false }
.Select(b => new WrappedBool(b));
Run Code Online (Sandbox Code Playgroud)
每当您调用它时,它都会创建一个新实例,List<bool>() {false, true, false}其中包含您false要迭代的项目
// new List<bool>() { false, true, false } - do we have any false item here?
// Yes - keep on looping (forever)
while (enumerable.Any(wb => !wb.InnerBool))
{
// get 1st false from new List<bool>() { false, true, false }
WrappedBool firstFalse = enumerable.Where(wb => !wb.InnerBool).First();
// turn it into true and discard
firstFalse.InnerBool = true;
}
Run Code Online (Sandbox Code Playgroud)
反之
IEnumerable<WrappedBool> enumerable =
new List<bool>() { false, true, false }
.Select(b => new WrappedBool(b))
.ToList(); // create a List; call new List<bool>() { false, true, false } just once
Run Code Online (Sandbox Code Playgroud)
被物化所以enumerable在List<T>其中创建一次,并在其中修改1日和3D项目:
// does enumerable collection (List) have any false item?
while (enumerable.Any(wb => !wb.InnerBool))
{
// get 1st false from enumerable List
WrappedBool firstFalse = enumerable.Where(wb => !wb.InnerBool).First();
// turn it into true
firstFalse.InnerBool = true;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |