C# ошибка. Оператор > невозможно применить к операнду типа T и T
Реализую свою коллекция наследуясь от интерфейса IList<Т>. Проблемы возникли с методом sort(хотела сделать пузырьковую сортировку)
public void BubbleSort()
{
for (int i = 0; i < Count; i++)
{
for (int j = 1; j < Count-1; j++)
{
if (_list[j] > _list[j - 1]) // здесь выдает ошибку
{
}
}
}
}
Ошибка: Оператор > невозможно применить к операнду типа T и T
В интернете посмотрела про это и нашла лишь CompareTo, но я не понимаю как с ним работать и что именно он делает.
Как мне все же сравнить элементы списка?
Ответы (2 шт):
Для произвольных типов операторы сравнения (> , < ...) неопределены, зато эти типы могут реализовывать интерфейс IComparable. Соответственно все сравнения через операторы вам нужно заменить на метод CompareTo и поставить ограничение на тип Tвида where T : IComparable<T>. CompareTo сравнивает один объект с другим и возвращает int, обычно < 0 означает что объект на котором вызывается метод меньше аргумента, > 0 - наоборот и == 0 - равны. Ну и да, все численные типы реализуют этот интерфейс, так что вам ничего реализовывать не надо.
Обобщения в C# работают в типобезопасном режиме. Это значит, что операции определенные для типа T должны быть определены для всех типов удовлетворяющих этому типу T. По-умолчанию для типа T доступны только операции, определенные для Object, так как все типы явно и неявно (через боксинг) наследуются от Object и мы можем гарантировать, что все что определено для Object так же определено и для T
Это основное отличие от, например, шаблонов C++, где ваш код был бы скомпилирован для удовлетворяющих этот шаблон типов.
Для наглядности вот вам пример в котором определены операции сравнения:
public class Clazz
{
private int _x;
public Clazz(int x)
{
_x = x;
}
public static bool operator <(Clazz a, Clazz b)
{
return a._x < b._x;
}
public static bool operator >(Clazz a, Clazz b)
{
return a._x > b._x;
}
}
Для Object не определены операции > или < поэтому такое определение обобщения не сработает:
private static bool Compare<T>(T a, T b)
{
return a > b;
}
Потому что сейчас для T можно подставить любой тип без ограничений. Но мы можем установить на T ограничение параметров-типов которые будут включать только те типы, для которых эти операции определены.
private static bool Compare<T>(T a, T b) where T : Clazz
{
return a > b;
}
И подставлять в качестве заполнителя типа как Clazz, так и производные от него классы. Та же механика распространяется и на случай с интерфейсом IComparable. Вам нужно так же ограничить тип T на работу только с типами, которые имплементируют этот интерфейс. Cм. ответ @SmorcIRL