自定义容器类成员的List< T> .Sort()与List< T> OrderBy()的实用程序 [英] Utility of List<T>.Sort() versus List<T>.OrderBy() for a member of a custom container class

查看:120
本文介绍了自定义容器类成员的List< T> .Sort()与List< T> OrderBy()的实用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现自己回过头来查看一些旧的3.5框架旧版代码,并且发现了一些必须以同步方式更新的列表和字典.我已经确定,通过将它们融合到新的自定义类的自定义容器类中,可以使此过程变得无限容易地被利用和理解.但是,在某些方面,我涉及到通过特定的内部属性来组织这些新容器类的内容的问题.例如,按一类的ID号属性排序.

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 a synchronized fashion. I've determined that I can make this process infinitely easier to both utilize and understand by converging these into custom container classes of new custom classes. There are some points, however, where I came to concerns with organizing the contents of these new container classes by a specific inner property. For example, sorting by the ID number property of one class.

由于容器类主要基于通用List对象,所以我的第一个直觉是使用IComparable编写内部类,并编写CompareTo方法来比较属性.这样,我想调用排序时就可以调用items.Sort().

As the container classes are primarily based around a generic List object, my first instinct was to write the inner classes with IComparable, and write the CompareTo method that compares the properties. This way, I can just call items.Sort() when I want to invoke the sorting.

但是,我一直在考虑使用items = items.OrderBy(Func)代替.这样,如果我需要按任何其他属性进行排序,它将更加灵活.可读性也更好,因为用于排序的属性将与sort调用内联列出,而不必查找IComparable代码.结果,整体实现感觉更干净.

However, I've been thinking instead about using items = items.OrderBy(Func) instead. This way it is more flexible if I need to sort by any other property. Readability is better as well, since the property used for sorting will be listed in-line with the sort call rather than having to look up the IComparable code. The overall implementation feels cleaner as a result.

我不在乎过早的优化或微优化,但我喜欢一致性.我发现最好在尽可能多的情况下坚持一种实现,并在必要时使用不同的实现.将我的代码转换为使用LINQ OrderBy而不是List.Sort是否值得?对于这些自定义容器,坚持使用IComparable实现是更好的做法吗?我应该权衡此决定的任何一条路径是否都具有任何明显的机械优势?还是它们的最终功能等同于只是成为编码人员的偏爱?

I don't care for premature or micro optimization, but I like consistency. I find it best to stick with one kind of implementation for as many cases as it is appropriate, and use different implementations where it is necessary. Is it worth it to convert my code to use the LINQ OrderBy instead of using List.Sort? Is it a better practice to stick with the IComparable implementation for these custom containers? Are there any significant mechanical advantages offered by either path that I should be weighing the decision on? Or is their end-functionality equivalent to the point that it just becomes coder's preference?

推荐答案

此处的重点是List<T>.Sort()进行适当的排序.如果您的列表暴露于外部代码,则它将始终代表与此代码相同的对象.如果列表通过容器类外部的代码保存在字段中,则这一点很重要.如果使用OrderBy()进行排序,则每次都会得到一个新的枚举,以替换以前的items.以前存储的任何列表都不会代表您班级的当前状态.

The major point here is that List<T>.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.

考虑到性能,OrderBy将必须遍历整个列表以对项目进行排序.然后,您将调用ToList()从该枚举创建新列表,并再次遍历该列表.另外,由于它是枚举,因此List将使用加倍算法,并增加其大小,直到每个元素都适合它为止.如果列表很大,那可能是相当多的分配和内存复制.我希望性能会比List<T>.Sort()差很多.

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<T>.Sort().

小型基准测试:

internal class Program {

    private static List<int> CreateList(int size) {

        // use the same seed so that every list has the same elements
        Random random = new Random(589134554);

        List<int> list = new List<int>(size);
        for (int i = 0; i < size; ++i)
            list.Add(random.Next());
        return list;
    }

    private static void Benchmark(int size, bool output = true) {
        List<int> list1 = CreateList(size);
        List<int> 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();
    }
}

输出(标准化为List.Sort):

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%)

这篇关于自定义容器类成员的List&lt; T&gt; .Sort()与List&lt; T&gt; OrderBy()的实用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆