我需要迭代一个对象列表,只为布尔属性设置为true的对象做一些事情 . 我正在讨论这段代码
foreach (RouteParameter parameter in parameters.Where(p => p.Condition))
{ //do something }
和这段代码
foreach (RouteParameter parameter in parameters)
{
if !parameter.Condition
continue;
//do something
}
第一个代码显然更清晰,但我怀疑它是一个巨大的列表所以我并不过分担心性能,但循环两次的想法只会让我感到烦恼 .
问题:如果没有循环两次,是否有一种干净/漂亮的方式来编写它?
4 回答
大多数Linq运算符(例如
Where
)都实现为支持 deferred and lazy execution . 在您的示例中,列表将仅迭代一次,因为位于Where
返回的IEnumerable后面的枚举器将枚举列表,直到找到与谓词匹配的项,产生它并且仅在被要求提供下一个元素时才会继续 .从代码的角度来看,我更喜欢使用where的变体,虽然可以说你可以为
parameters.Where(p => p.Condition)
声明一个本地 .强烈建议使用Jon Skeet的Edulinq系列,阅读这些内容可以帮助您理解LINQ运算符 .
Jon Skeet有时会做一个真人LINQ演示来解释它是如何工作的 . 想象一下,你有三个人在舞台上 . 在左边,我们有一个人有一个洗牌的牌 . 在中间我们有一个人只能传递红牌,在右边,我们有一个人想要牌 .
右边的那个人在中间捅了那个家伙 . 中间的那个人捅了左边的那个人 . 左边的那个人把中间的那个人递给了一张牌 . 如果它是黑色的,那么中间的那个人把它扔在地板上然后再次戳,直到他得到一张红牌,然后他将牌递给右边的那个人 . 然后右边的那个人又把那个中间人捅了出来 .
这种情况一直持续到左边的那个人用完纸牌 .
The deck was not gone through from start to finish more than once. 然而,左边的那个人和中间的人都处理了52张牌,而右边的那个人处理了26张牌 . 卡片上总共有52 52 26次操作,但是套牌只进行了一次 .
你的“LINQ”版本和“继续”版本是一回事;如果你有
然后有52个操作从牌组中取出每张牌,52个操作测试每张牌是否为黑色,以及26个操作在红牌上 . 同样的事情 .
实际上,它不是"looping twice."
.Where
子句使用延迟执行 . 换句话说,当你调用.Where
时几乎没有工作,但是当你遍历结果时,它会迭代原始列表并只传递符合你条件的项目 . 如果您根据代码的执行方式来考虑它,那么您实际上是这样做的:作为一种风格问题,我个人更喜欢以下内容:
我更喜欢这个: