首页 文章

LINQ Foreach vs Foreach If

提问于
浏览
54

我需要迭代一个对象列表,只为布尔属性设置为true的对象做一些事情 . 我正在讨论这段代码

foreach (RouteParameter parameter in parameters.Where(p => p.Condition))
{ //do something }

和这段代码

foreach (RouteParameter parameter in parameters)
{ 
  if !parameter.Condition
    continue;
  //do something
}

第一个代码显然更清晰,但我怀疑它是一个巨大的列表所以我并不过分担心性能,但循环两次的想法只会让我感到烦恼 .

问题:如果没有循环两次,是否有一种干净/漂亮的方式来编写它?

4 回答

  • -3

    大多数Linq运算符(例如 Where )都实现为支持 deferred and lazy execution . 在您的示例中,列表将仅迭代一次,因为位于 Where 返回的IEnumerable后面的枚举器将枚举列表,直到找到与谓词匹配的项,产生它并且仅在被要求提供下一个元素时才会继续 .

    从代码的角度来看,我更喜欢使用where的变体,虽然可以说你可以为 parameters.Where(p => p.Condition) 声明一个本地 .

    强烈建议使用Jon Skeet的Edulinq系列,阅读这些内容可以帮助您理解LINQ运算符 .

  • 26

    Jon Skeet有时会做一个真人LINQ演示来解释它是如何工作的 . 想象一下,你有三个人在舞台上 . 在左边,我们有一个人有一个洗牌的牌 . 在中间我们有一个人只能传递红牌,在右边,我们有一个人想要牌 .

    右边的那个人在中间捅了那个家伙 . 中间的那个人捅了左边的那个人 . 左边的那个人把中间的那个人递给了一张牌 . 如果它是黑色的,那么中间的那个人把它扔在地板上然后再次戳,直到他得到一张红牌,然后他将牌递给右边的那个人 . 然后右边的那个人又把那个中间人捅了出来 .

    这种情况一直持续到左边的那个人用完纸牌 .

    The deck was not gone through from start to finish more than once. 然而,左边的那个人和中间的人都处理了52张牌,而右边的那个人处理了26张牌 . 卡片上总共有52 52 26次操作,但是套牌只进行了一次 .

    你的“LINQ”版本和“继续”版本是一回事;如果你有

    foreach(var card in deck)
    {
        if (card.IsBlack) continue;
        ... use card ...
    

    然后有52个操作从牌组中取出每张牌,52个操作测试每张牌是否为黑色,以及26个操作在红牌上 . 同样的事情 .

  • 35

    实际上,它不是"looping twice." .Where 子句使用延迟执行 . 换句话说,当你调用 .Where 时几乎没有工作,但是当你遍历结果时,它会迭代原始列表并只传递符合你条件的项目 . 如果您根据代码的执行方式来考虑它,那么您实际上是这样做的:

    Func<Parameter, bool> matchesCondition = p => p.Condition;
    foreach(var parameter in parameters)
    {
        if(matchesCondition(parameter))
        {
            ...
        }
    }
    

    作为一种风格问题,我个人更喜欢以下内容:

    var matchingParameters = parameters.Where(p => p.Condition);
    foreach(var parameter in matchingParameters)
    {
    }
    
  • 125

    我更喜欢这个:

    theList.Where(itm => itm.Condition).ToList().ForEach(itmFE => { itmFe.DoSomething(); });
    

相关问题