#c# #linq #compareto #icomparable
#c# #linq #сравнение #icomparable
Вопрос:
У меня есть список Versions
.
List<Version> versions = GetVersions();
И у меня есть selectedVersion
.
Мой Version
класс реализует IComparable
.
public class Version : IComparable<Version>
Так что я могу сделать versions.Sort()
. На данный момент мои Version
объекты отсортированы в списке, скажем, по Name
свойству.
Из списка Versions
я хотел бы получить элементы, которые выше моего selectedVersion
. Как я могу это сделать с помощью Linq?
То, что я пробовал, — это приведение selectedVersion
к IComparable
, а затем использование CompareTo
, но я получаю InvalidCastException
сообщение об ошибке.
IComparable comparable = (IComparable)selectedVersion;
if(comparable.CompareTo(selectedVersion)) > 0
Комментарии:
1. Почему вы приводите к
IComparable
тому, что версия только реализуетIComparable<Version>
?2. IComparable — это метод сравнения объектов, в то время как selectedVersion — это версия типа.
3. @PatrickHuizinga отметил. Я должен приводить к
IComparable<Version>
Ответ №1:
Правильный способ — использовать Comparer<T>.Default
which будет работать, как только тип T
реализует либо IComparable<T>
или IComparable
:
var result = versions
.Where(version => Comparer<Version>.Default.Compare(version, selectedVersion) > 0)
.ToList();
Вы даже можете инкапсулировать его в пользовательский метод расширения (так что вы DRY):
public static class EnumerableExtensions
{
public static IEnumerable<T> GreaterThan<T>(this IEnumerable<T> source, T value, IComparer<T> comparer = null)
{
if (comparer == null) comparer = Comparer<T>.Defau<
return source.Where(item => comparer.Compare(item, value) > 0);
}
}
и использовать просто
var result = versions.GreaterThan(selectedVersion).ToList();
Комментарии:
1. Обходной путь? Он-он, это то, что
OrderBy
,Min
,Max
внутренне используется, когда вы не указываете явный компаратор, поэтому, я думаю, они считают это решением 🙂2. Значит, он все еще зависит от моей
CompareTo
реализации?3. Абсолютно. Вы можете поставить точку останова и посмотреть. Это просто универсальный метод, поэтому вам не нужно думать, какой именно интерфейс реализован классом.
4. тогда это более общее решение 🙂
Ответ №2:
Похоже, вы реализовали IComparable<T>
, что не совпадает с IComparable
. Либо реализуйте IComparable
, либо приведите к IComparable<Version>
, и вы сможете делать то, что хотите.
Ответ №3:
versions.Where(x => x.CompareTo(selectedVersion) > 0).ToList();
или, если IComparable<Version>
реализовано явно:
versions.Where(x => (x as IComparable<Version>).CompareTo(selectedVersion) > 0).ToList();