Почему нет сортировки для IList <T>?!?! (Изм)

Я был очень удивлен, когда обнаружил, что нет прямого способа сортировки или выполнения бинарного поиска в IList <T> . Точно так же, как есть статические методы для сортировки и выполнения двоичного поиска в массиве, я считаю, что было бы очень полезно иметь аналогичные статические методы, которые принимают IList <T> .

В настоящее время

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);
}

Я взглянул на SDK.NET Framework 4.0 Beta и там еще не является решением этой проблемы.

Я знаю, что я мог бы обойти это, создав метод расширения, который проверяет, является ли это List <T> , а затем сортировка/поиск с использованием списка <T> экземпляр; однако, если это не экземпляр списка <T> , тогда я должен выполнить копию (которая воняет для очень больших списков). Я знаю, что могу все это сделать, но почему? Есть ли причина, по которой они специально упустили эту функцию?

Чтобы попытаться получить это в .NET 4.0 Framework, я создал предложение через программу Microsoft Connect. Если вы расстроены, как я, по этому вопросу, проголосуйте за него и, возможно, он будет добавлен.

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

Ответ 1

LINQ имеет метод OrderBy, который работает на всех IEnumerable <T> , включая IList <T> . Вы можете сделать то же самое, используя OrderBy.

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

Ответ 2

Я думаю, что неплохой вариант для того, чтобы не включать метод сортировки для IList<T>. Во-первых, это создало бы дополнительную сложность для тех, кто хочет реализовать IList, а во-вторых, это затруднит соответствие интерфейса IList Принцип разделения интерфейса.

В общем, что я делаю, если мне нужно выполнить сортировку на IList<T>, создайте новый List<T> и передайте IList<T> в качестве параметра

так, например:

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

Ответ 3

Хорошей новостью является то, что вы можете писать такие методы довольно легко; и благодаря методам расширения С# 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 re-write Sort;-p); но после этого:

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

Важно отметить, что IList<T> имеет индекс чтения/записи, поэтому, безусловно, возможно выполнить сортировку и двоичный поиск без взлома выше.

Ответ 4

У вас есть ArrayList.Adapter, который позволяет использовать процедуры сортировки ArrayList, но это вызовет огромное влияние производительности на общие списки типов unboxed значений, а также накладные расходы на виртуальный вызов и интерфейс.

Как для ссылочных, так и для типов значений, диспетчеризация интерфейса может быть дорогостоящей, то есть вызов ICollection<T>.CopyTo массив T[], за которым следует отдельный сортировка, может быть самым быстрым вариантом общего назначения, включая настраиваемое расширение для прямого сортировки на IList<T> объект.

List<T> имеет метод Sort, поскольку он может очень эффективно работать с базовым массивом типа T[]. Нет простого способа сделать это для произвольного IList<T>.

Ответ 5

Я не эксперт на С#, но очень немногие реализации List поддерживают сортировку, двоичный поиск или даже индексированный поиск. Списки обычно основаны на связанных списках, которые обычно не предлагают способ O(1) получить элемент по его индексу. Если вы хотите быстро найти элемент, используйте то, что хранит элементы в отсортированном порядке, например tree или массив, как это было предложено другие.

Я нахожу тот факт, что IList содержит индексный метод извлечения. Возможно, вы захотите использовать SortedList вместо List, так как похоже, что он должен поддерживать поиск по индексу или ключу в O(1) время. В общем случае, если вам нужно что-то, что поддерживает быстрый поиск, тогда найдите структуру данных, которая сохраняет свои элементы в порядке, а не сортирует их явно. Если ничего больше, у С# уже есть уже иная структура данных.