为什么IList <t>没有排序?!?! (编辑)的</T>

时间:2009-07-20 02:50:00

标签: c# .net c#-4.0

当我发现没有直接的方法来对IList进行排序或执行二进制搜索时,我感到非常惊讶。 T>。就像有静态方法对数组进行排序和执行二进制搜索一样,我认为使用类似于IList的静态方法非常有帮助。 T&gt;。

目前:

class Array
{
    static Sort<T>(T[] array);
    static int BinarySearch<T>(T[] array, T item);
}

我希望他们补充一下:

class List
{
    static Sort<T>(IList<T> list);
    static int BinarySearch<T>(IList<T> list, T item);
}

我瞥了一眼.NET Framework 4.0 Beta SDK,仍然似乎不是这个问题的解决方案。

我知道我可以通过创建一个检查它是否是List&lt;的扩展方法来解决这个问题。 T>然后使用List&lt;进行排序/搜索T>实例;但是,如果它不是List的实例&lt; T&gt ;,然后我必须执行一个副本(对于非常大的列表很臭)。我知道我可以做到这一切,但为什么呢?有没有理由他们故意省略这个功能?

为了尝试在.NET 4.0 Framework中获取此功能,我通过Microsoft的Connect程序创建了一个建议。如果你像我一样对这个问题感到沮丧,那就投票吧,也许它会被添加。

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=474201

5 个答案:

答案 0 :(得分:17)

LINQ有一个OrderBy方法,适用于所有IEnumerable&lt; T&gt;,包括IList&lt; T&gt;。你可以使用OrderBy完成同样的事情。

// Order a list of addresses:
IList<string> list = ...
var orderedList = list.OrderBy(input => input);

答案 1 :(得分:10)

我认为不包括IList<T>的排序方法是一个很好的例子。首先,它会为那些想要实现IList的人带来额外的复杂性,第二,它会使IList接口更难以符合Interface Segregation Principle

一般情况下,如果我需要对IList<T>执行排序,我会创建一个新的List<T>,并将IList<T>作为参数传递

所以例如:

        public IList<Address> SortAddresses(IList<Address> addresses)
        {
            var sortedAddresses = new List<Address>(addresses);
            sortedAddresses.Sort();
            return sortedAddresses;
        }

答案 2 :(得分:4)

好消息是你可以很容易地这样的方法;并且由于C#3.0扩展方法,您可以在界面上进行此操作:

public static class ListExt
{
    public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) {
        foreach(T item in items) list.Add(item);
    }
    public static void Sort<T>(this IList<T> list) {
        Sort<T>(list,Comparer<T>.Default); // ordinal sort by default
    }
    public static void Sort<T>(this IList<T> list, IComparer<T> comparer)
    { // very poor implementation!
        List<T> concreteList = new List<T>(list);
        concreteList.Sort(comparer); // cheat!
        list.Clear();
        list.AddRange(concreteList);
    }
    public static int BinarySearch<T>(this IList<T> list, T item) {
        return BinarySearch<T>(list, item, Comparer<T>.Default);
    }
    public static int BinarySearch<T>(this IList<T> list, T item,
        IComparer<T> comparer)
    {...} // TODO
}

现在剩下的就是TODO代码本身(和probaby重写Sort ;-p);但在那之后:

IList<T> list = ...
list.Sort();
T huntFor = ...
int i = list.BinarySearch(huntFor);

重要的是,IList<T>有一个读/写索引器,所以当然可以在没有上面的黑客攻击的情况下进行排序和二进制搜索。

答案 3 :(得分:2)

你有ArrayList.Adapter允许使用ArrayList的排序例程,但它会对未装箱值类型的通用列表产生巨大的性能影响,加上虚拟调用和接口调度开销

对于引用和值类型,接口调度可能很昂贵,这意味着调用ICollection<T>.CopyTo数组T[]后跟单独排序可能是最快的通用选项,包括自定义扩展到直接对IList<T>对象进行排序。

List<T>有一个Sort方法,因为它可以非常有效地对T[]类型的基础数组进行操作。对于任意IList<T>,根本无法做到这一点。

答案 4 :(得分:0)

我不是C#专家,但很少有List实现支持排序,二进制搜索甚至索引检索。列表通常基于linked lists,它通常不提供通过其索引检索项目的O(1)方式。如果你想快速定位一个元素,那就用一些东西来保持元素的排序顺序,如tree或其他人建议的数组。

我确实发现IList包含indexed retrieval method有趣的事实。您可能需要考虑使用SortedList而不是List,因为它看起来应该支持在O(1)时间内通过索引或键进行查找。通常,如果您需要支持快速查找的内容,那么请查找保持其元素顺序而不是显式排序的数据结构。如果不出意外,C#已经有了很多数据结构。