c# - Why does Select turn my while loop into an infinite loop?
问题描述
At work I ran into a strange problem, where a loop I expected to terminate was actually running indefinitely.
I traced the problem back to a use of Select
.
Interestingly, the loop terminated as expected when I added a .ToList()
right after the Select
. I boiled it down to a small example.
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;
}
While I don't have to deal with my code not terminating anymore, I still wonder where this behaviour is coming from in the first place.
解决方案
好吧,没有具体化( .ToList()
)enumerable
只是一个查询
IEnumerable<WrappedBool> enumerable =
new List<bool>() { false, true, false }
.Select(b => new WrappedBool(b));
每当您调用它时,它都会创建一个新实例,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;
}
相反
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
是物化的,所以enumerable
它List<T>
是创建一次并在其中修改 1st 和 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;
}
推荐阅读
- firebase - 强制 Firestore 数组与已经是数组一部分的值合并
- python - HexString 到打包的 EBCDIC 字符串
- html - 如何通过特定索引设置文本样式?
- python - 如何在python中将最多63位的数字转换为单词?
- haskell - Haskell:开头的函数解析错误
- swift - 当主类的超类为 UICollectionViewCell 时,如何从单元格执行Segue 或转到另一个视图
- java - List 和 LinkedList 之间的类型不兼容
- r - 在R中同时对多行数据帧进行操作
- c# - 我是否正确使用 try catch?
- android - Android - 如何沿路径动画颜色变化