IComparable
работает только в одну сторону
Допустим, у вас есть Employee
класс. В одном представлении вы хотите показать все Employees
отсортированные по имени - в другом по адресу. Как вы собираетесь достичь этого? Не с IComparable
, по крайней мере, никаким идиоматическим способом.
IComparable
имеет логику в неправильном месте
Интерфейс используется при вызове .Sort()
. В представлении, отображающем Customer
отсортированный по имени, вообще нет кода, который бы указывал, как он будет сортироваться.
С другой стороны, Customer
класс предполагает, как он будет использоваться - в этом случае он будет использоваться в списке, отсортированном по именам.
IComparable
используется неявно
По сравнению с альтернативами очень трудно увидеть, где используется логика сравнения - или вообще. Предполагая вашу стандартную среду разработки и начиная с Customer
класса, мне придется
- Поиск всех ссылок на
Customer
- Найдите те ссылки, которые используются в списке
- Проверьте,
.Sort()
вызывали ли эти списки их
Что еще хуже, если вы удалите IComparable
реализацию, которая все еще используется, вы не получите никаких ошибок или предупреждений. Единственное, что вы получите, - это неправильное поведение во всех местах, которые были слишком неясны для вас.
Эти проблемы объединены, плюс меняющиеся требования
Сама причина, по которой я начал думать об этом, заключается в том, что для меня это пошло не так. Я успешно использую IComparable
в своем приложении в течение 2 лет. Теперь требования изменились, и вещь должна быть отсортирована двумя разными способами. Заметили, что неинтересно проходить шаги, описанные в предыдущем разделе.
Вопрос
Эти проблемы заставляют меня думать, IComparable
что я уступаю IComparer
или .OrderBy()
, до такой степени, что не вижу ни одного действительного варианта использования, который не будет лучше обслуживаться альтернативами.
Всегда ли лучше использовать IComparer
или LINQ, или я не вижу здесь преимуществ / вариантов использования?
источник
IComparable
, что подтверждает мою точку зрения.SortedXXX
коллекции, они либо требуют, чтобы сохраненные элементы были,IComparable
либо чтобы они былиIComparer
предоставлены. Также обратите внимание, что тривиально изменить порядок естественной сортировки с помощью одного компаратора и заставить его работать со всемиIComparable
объектами.IComparable
считается механизмом сравнения по умолчанию .IComparer
используется, когда вы хотите переопределить механизм сравнения по умолчанию.ReverseComparer<T>
: gist.github.com/jackfarrington/078e7af7bc82482aa634Ответы:
IComparable
имеет ограничения, которые вы упомянули, это правильно. Это интерфейс, который уже был доступен в .NET Framework 1.0, где эти функциональные альтернативы и Linq были недоступны. Так что да, это можно рассматривать как устаревший элемент инфраструктуры, который в основном сохраняется для обратной совместимости.Однако для многих простых структур данных один из способов сортировки, вероятно, достаточно или естественен. В этих случаях наличие одного канонического места для реализации отношения порядка все еще является хорошим способом сохранить код СУХИМ, вместо того, чтобы всегда повторять одну и ту же логику при каждом вызове
OrderBy
повсюду.Как вы писали, вы «счастливо используете IComparable в своем приложении уже 2 года», так что, как мне кажется, он долгое время служил вам хорошо. Когда вам теперь нужно проверять, изменять и тестировать все вызовы
Sort
, это также может быть признаком того, что вы выполняете одну и ту же логику сортировки во многих местах, что не является ошибкойIComparable
. Так что это может быть поводом для централизации большей части этой логики в одном месте, делая ваш код более СУХИМЫМ.источник
IComparable
, весь существующий код сортировки остался бы нетронутым в их соответствующих представлениях, в то время как я бы добавил только новый код сортировки для нового представления.IComparable
написанной вами реализации?IComparable
вы получаете реализацию по умолчанию бесплатно, а иногда вам даже не нужно писать эту реализацию.BigInteger
. Если бы он не реализовывал операторы / интерфейсы сравнения, как бы вы реализовали IComparer самостоятельно ? Вам понадобится доступ к внутренним структурам данных, чтобы сделать это эффективно или вообще. Предположим, у вас есть такой тип, как Customer; общедоступные свойства, по которым вы хотите отсортировать , имеют компараторы. Для меня в этом разница: реализовать,IComparable<T>
если было бы неразумно ожидать, что вызывающая сторона будет реализовывать компаратор.If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.
Просто потому чтоIComparable
был лучше в то время это решение , не означает, что это лучшее решение сегодня . Ваш первый комментарий здесь подразумевает, что «это сопоставимо или ничего», что не соответствует действительности, проблема могла быть решена различными способами. Приложения могут увеличиваться в размере / масштабе, а вещи, которые раньше выглядели подходящими, могут не соответствовать растущим требованиям приложения.Я согласен с вашими чувствами по поводу
IComparable
Просто посмотрите на замечания по
Array.Sort()
IComparable
интерфейс для возможности сравнения с любым другим элементом массива. (или исключение выдается)Мы, вероятно, никогда не будем сейчас мотивации, однако! рассматривать
object.Equals()
метод для каждого объекта, который позволяет сравнивать объекты друг с другом, чтобы увидеть, являются ли они «одинаковыми»У вас это уже есть, но вам нужно было добавить, что
Array.Sort()
вы можете добавитьobject.Compare(object)
источник