代码之家  ›  专栏  ›  技术社区  ›  snemarch

LINQ或foreach-风格/可读性和速度

  •  6
  • snemarch  · 技术社区  · 15 年前

    我有一段验证逻辑的代码,一般来说是这样的:

    private bool AllItemsAreSatisfactoryV1(IEnumerable<Source> collection)
    {
        foreach(var foo in collection)
        {
            Target target = SomeFancyLookup(foo);
            if (!target.Satisfactory)
            {
                return false;
            }
        }
        return true;
    }
    

    这是工作,是相当容易理解,并有早期的优化。然而,这是相当冗长的。这个问题的主要目的是什么被认为是可读性和良好的风格。我也对表演感兴趣;我坚信 过早的{优化,悲观}是万恶之源

    我对LINQ还很陌生,所以我想对我提出的两个备选版本发表一些评论,以及任何其他建议。可读性。

    private bool AllItemsAreSatisfactoryV2(IEnumerable<Source> collection)
    {
        return null ==
            (from foo in collection
            where !(SomeFancyLookup(foo).Satisfactory)
            select foo).First();
    }
    
    private bool AllItemsAreSatisfactoryV3(IEnumerable<Source> collection)
    {
        return !collection.Any(foo => !SomeFancyLookup(foo).Satisfactory);
    }
    

    我不相信V2在可读性方面比V1好多少,即使更短。我觉得V3很简洁明了,但我不太喜欢 Method().Property 部分;当然我可以将lambda转换为一个完整的委托,但是它失去了它的一行优雅。

    我想评论的是:

    1. 风格-曾经如此主观,但你觉得什么是可读的?
    2. 性能-这些都是一个明确的不?据我所知,这三种方法都应该尽早推出。
    3. 可调试性-有什么需要考虑的吗?

    提前感谢:)

    2 回复  |  直到 15 年前
        1
  •  13
  •   Lee    15 年前

    我想 All

    private bool AllItemsAreSatisfactoryV1(IEnumerable<Source> collection)
    {
        return collection.Select(f => SomeFancyLookup(f)).All(t => t.Satisfactory);
    }
    

    我认为,在这里使用linq不太可能在常规foreach循环上造成性能问题,尽管如果它这样做了就可以直接进行更改。

        2
  •  1
  •   KeithS    15 年前

    V2很难理解它的意图,并且在它当前的形式中会抛出一个异常(First()要求源IEnumerable不能为空;我认为您正在寻找FirstOrDefault())。为什么不在末尾加上Any(),而不是将列表中的结果与null进行比较呢?

    实际上,这三种方法都可以归结为非常相似的操作码;遍历集合,调用SomeFancyLookup(),并检查其返回值的属性;在第一次失败时退出。Any()“隐藏”一个非常类似的foreach算法。V1和所有其他变量之间的区别是使用了一个命名变量,这可能性能稍差一些,但在所有三种情况下都有一个对目标的引用,所以我怀疑它是否有意义,如果存在差异的话。