我需要迭代一个对象列表,只为布尔属性设置为true的对象做一些事情.我正在讨论这段代码
foreach (RouteParameter parameter in parameters.Where(p => p.Condition))
{ //do something }
Run Code Online (Sandbox Code Playgroud)
和这段代码
foreach (RouteParameter parameter in parameters)
{
if !parameter.Condition
continue;
//do something
}
Run Code Online (Sandbox Code Playgroud)
第一个代码显然更干净,但我怀疑它会在列表上循环两次 - 一次用于查询,一次用于foreach.这会不会是一个巨大的名单,所以我不是太在意性能,但两次循环刚的想法的错误我.
问题:如果没有循环两次,是否有一种干净/漂亮的方式来编写它?
Eri*_*ert 130
Jon Skeet有时会做一个真人LINQ演示来解释它是如何工作的.想象一下,你有三个人在舞台上.在左边,我们有一个人有一个洗牌的牌.在中间我们有一个人只能传递红牌,在右边,我们有一个人想要牌.
右边的那个人在中间捅了那个家伙.中间的那个人捅了左边的那个人.左边的那个人把中间的那个人递给了一张牌.如果它是黑色的,那么中间的那个人把它扔在地板上然后再次戳,直到他得到一张红牌,然后他将牌递给右边的那个人.然后右边的那个人又把那个中间人捅了出来.
这种情况一直持续到左边的那个人用完纸牌.
甲板从头到尾不止一次经过.然而,左边的那个人和中间的那个人处理了52张牌,而右边的那个人处理了26张牌.卡上总共有52 + 52 + 26次操作,但是牌组只进行了一次.
你的"LINQ"版本和"继续"版本是一回事; 如果你有
foreach(var card in deck)
{
if (card.IsBlack) continue;
... use card ...
Run Code Online (Sandbox Code Playgroud)
然后有52个操作从牌组中取出每张牌,52个操作测试每张牌是否为黑色,以及26个操作在红牌上.同样的事情.
Str*_*ior 27
实际上,它不是"循环两次".该.Where子句使用延迟执行.换句话说,实际上在调用时不会执行任何工作.Where,但是当您遍历结果时,它将遍历原始列表并仅传递符合您条件的项目.如果您根据代码的执行方式来考虑它,那么您实际上是这样做的:
Func<Parameter, bool> matchesCondition = p => p.Condition;
foreach(var parameter in parameters)
{
if(matchesCondition(parameter))
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
作为一种风格问题,我个人更喜欢以下内容:
var matchingParameters = parameters.Where(p => p.Condition);
foreach(var parameter in matchingParameters)
{
}
Run Code Online (Sandbox Code Playgroud)