为什么IList 没有排序?!?! (编辑)的
当我发现没有直接的方法对IList 进行排序或执行二进制搜索时,我感到非常惊讶。 就像有一些静态方法来对数组进行排序和执行二进制搜索一样,我认为使用类似于IList 的静态方法会非常有帮助。
目前:
class Array { static Sort(T[] array); static int BinarySearch(T[] array, T item); }
我希望他们会补充:
class List { static Sort(IList list); static int BinarySearch(IList list, T item); }
我瞥了一眼.NET Framework 4.0 Beta SDK,似乎仍然没有解决这个问题的方法。
我知道我可以通过创建一个扩展方法来解决这个问题,该方法检查它是否是List 然后使用List 实例进行排序/搜索; 但是,如果它不是List 的实例,那么我必须执行一个副本(对于非常大的列表很臭)。 我知道我可以做到这一切,但为什么呢? 有没有理由他们故意省略这个function?
为了尝试在.NET 4.0 Framework中实现这一点,我通过Microsoft的Connect程序创建了一个建议。 如果你像我一样对这个问题感到沮丧,那就投票吧,也许它会被添加。
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=474201
LINQ有一个OrderBy方法,适用于所有IEnumerable
// Order a list of addresses: IList list = ... var orderedList = list.OrderBy(input => input);
我认为不包括IList
的排序方法是一个很好的例子。 首先,它会为那些想要实现IList的人带来额外的复杂性,第二,它会使IList接口更难以符合接口隔离原则 。
一般来说,如果我需要对IList
执行排序,我会创建一个新的List
并传入IList
作为参数
例如:
public IList SortAddresses(IList addresses) { var sortedAddresses = new List(addresses); sortedAddresses.Sort(); return sortedAddresses; }
好消息是你可以很容易地写出这样的方法; 并且感谢C#3.0扩展方法,您可以在界面上进行此操作:
public static class ListExt { public static void AddRange(this IList list, IEnumerable items) { foreach(T item in items) list.Add(item); } public static void Sort (this IList list) { Sort (list,Comparer .Default); // ordinal sort by default } public static void Sort (this IList list, IComparer comparer) { // very poor implementation! List concreteList = new List (list); concreteList.Sort(comparer); // cheat! list.Clear(); list.AddRange(concreteList); } public static int BinarySearch (this IList list, T item) { return BinarySearch (list, item, Comparer .Default); } public static int BinarySearch (this IList list, T item, IComparer comparer) {...} // TODO }
现在剩下的就是TODO代码本身(和probaby重写Sort
;-p); 但在那之后:
IList list = ... list.Sort(); T huntFor = ... int i = list.BinarySearch(huntFor);
重要的是, IList
有一个读/写索引器,所以当然可以在没有上面的hack的情况下进行排序和二进制搜索。
你确实有ArrayList.Adapter
允许使用ArrayList
的排序例程,但它会对未装箱值类型的通用列表,以及虚拟调用和接口调度开销产生巨大的性能影响。
对于引用和值类型,接口调度可能很昂贵,这意味着调用ICollection
数组T[]
后跟单独的排序可能是最快的通用选项,包括直接排序的自定义扩展IList
对象。
List
有一个Sort
方法,因为它可以非常有效地对T[]
类型的底层数组进行操作。 对于任意IList
根本无法做到这一点。
我不是C#专家,但很少有List实现支持排序,二进制搜索甚至索引检索。 列表通常基于链表 ,这些链表通常不提供通过其索引检索项的O(1)
方式。 如果要快速定位元素,则使用某些内容按照其他人的建议将元素按照排序顺序保存,如树或数组。
我确实发现IList
包含一个有趣的索引检索方法 。 您可能想要考虑使用SortedList
而不是List
因为它看起来应该支持在O(1)
时间内通过索引或键进行查找。 通常,如果您需要支持快速查找的内容,那么请查找保持其元素顺序而不是显式排序的数据结构。 如果不出意外,C#已经有了很多数据结构。