Utility of List.Sort() versus List.OrderBy() for a member of a custom container class

前端 未结 2 2006
暖寄归人
暖寄归人 2021-02-06 04:03

I\'ve found myself running back through some old 3.5 framework legacy code, and found some points where there are a whole bunch of lists and dictionaries that must be updated in

2条回答
  •  佛祖请我去吃肉
    2021-02-06 04:20

    The major point here is that List.Sort() does the sorting in place. If your list is exposed to external code, it will always represent the same object to this code. This is important if the list is kept in a field by code outside of the container class. If you're sorting with OrderBy(), you'll get a new enumeration each time, replacing the previous items. Any previously stored list will not represent the current state of your class.

    Considering performance, OrderBy will have to iterate through the whole list to sort items. Then you will call ToList() to create the new list from this enumeration, iterating through the list a second time. Plus, since it's an enumeration, List will use the doubling algorithm, increasing its size until every element can fit into it. In case of a large list, that could be quite a few allocations and memory copying. I would expect performance to be much worse than List.Sort().

    Edit: Small benchmark:

    internal class Program {
    
        private static List CreateList(int size) {
    
            // use the same seed so that every list has the same elements
            Random random = new Random(589134554);
    
            List list = new List(size);
            for (int i = 0; i < size; ++i)
                list.Add(random.Next());
            return list;
        }
    
        private static void Benchmark(int size, bool output = true) {
            List list1 = CreateList(size);
            List list2 = CreateList(size);
    
            Stopwatch stopwatch = Stopwatch.StartNew();
            list1.Sort();
            stopwatch.Stop();
            double elapsedSort = stopwatch.Elapsed.TotalMilliseconds;
            if (output)
                Console.WriteLine("List({0}).Sort(): {1}ms (100%)", size, elapsedSort);
    
            stopwatch.Restart();
            list2.OrderBy(i => i).ToList();
            stopwatch.Stop();
            double elapsedOrderBy = stopwatch.Elapsed.TotalMilliseconds;
            if (output)
                Console.WriteLine("List({0}).OrderBy(): {1}ms ({2:.00%})", size, elapsedOrderBy, elapsedOrderBy / elapsedSort);
    
        }
    
        internal static void Main() {
    
            // ensure linq library is loaded and initialized
            Benchmark(1000, false);
    
            Benchmark(10);
            Benchmark(100);
            Benchmark(1000);
            Benchmark(10000);
            Benchmark(100000);
            Benchmark(1000000);
    
            Console.ReadKey();
        }
    }
    

    Output (normalized to List.Sort):

    List(10).Sort(): 0,0025ms (100%)
    List(10).OrderBy(): 0,0157ms (628,00%)
    List(100).Sort(): 0,0068ms (100%)
    List(100).OrderBy(): 0,0294ms (432,35%)
    List(1000).Sort(): 0,0758ms (100%)
    List(1000).OrderBy(): 0,3107ms (409,89%)
    List(10000).Sort(): 0,8969ms (100%)
    List(10000).OrderBy(): 4,0751ms (454,35%)
    List(100000).Sort(): 10,8541ms (100%)
    List(100000).OrderBy(): 50,3497ms (463,88%)
    List(1000000).Sort(): 124,1001ms (100%)
    List(1000000).OrderBy(): 705,0707ms (568,15%)
    

提交回复
热议问题