4

以下代码提供了两种方法来生成总和小于 100 的整数对,并且它们根据与 (0,0) 的距离以降序排列。

    //approach 1
    private static IEnumerable<Tuple<int,int>>  ProduceIndices3()
    {
        var storage = new List<Tuple<int, int>>();
        for (int x = 0; x < 100; x++)
        {
            for (int y = 0; y < 100; y++)
            {
                if (x + y < 100)
                    storage.Add(Tuple.Create(x, y));
            }
        }
        storage.Sort((p1,p2) =>
           (p2.Item1 * p2.Item1 + 
           p2.Item2 * p2.Item2).CompareTo(
           p1.Item1 * p1.Item1 +
           p1.Item2 * p1.Item2));
        return storage;
    }

    //approach 2
    private static IEnumerable<Tuple<int, int>> QueryIndices3()
    {
        return from x in Enumerable.Range(0, 100)
               from y in Enumerable.Range(0, 100)
               where x + y < 100
               orderby (x * x + y * y) descending
               select Tuple.Create(x, y);
    }

这段代码摘自 Bill Wagner 的《Effective C# 》一书,第 8 条。在整篇文章中,作者更多地关注代码的语法、紧凑性和可读性,而很少关注性能,几乎没有讨论它。

所以我基本上想知道,哪种方法更快?什么通常在性能上更好(通常):查询语法或手动循环?

请详细讨论它们,如果有的话,请提供参考。:-)

4

3 回答 3

9

分析是事实,但我的直觉是循环可能更快。重要的是,100 次中有 99 次的性能差异在宏伟的计划中并不重要。使用更具可读性的版本,当您以后需要维护它时,您未来的自己会感谢您。

于 2011-01-20T19:28:41.490 回答
4

运行每个函数 1000 次:

for 循环:2623 毫秒查询:2821 毫秒

看起来合乎逻辑,因为第二个只是第一个的语法糖。但我会使用第二个来提高它的可读性。

于 2011-01-20T19:46:57.027 回答
1

尽管这并不能严格回答您的问题,但在性能方面,我建议将 x+y 逻辑合并到迭代中,因此:

for (int x = 0; x < 100; x++)
    for (int y = 0; y < 100 - x; y++)
        storage.Add(Tuple.Create(x, y));
于 2011-01-20T19:33:20.373 回答