У меня проблема с IComparable и методом сортировки коллекции - PullRequest
7 голосов
/ 02 февраля 2009

Хорошо, у меня есть сценарий, похожий на приведенный ниже код, у меня есть родительский класс, реализующий IComparable, и дочерний класс.

class Parent : IComparable<Parent> 
class Child : Parent

Child a = new Child();
Child b = new Child();
a.CompareTo(b);

Теперь вышеприведенное работает отлично, я могу сравнить два дочерних объекта друг с другом без проблем

List<Child> l = new List<Child>();
l.Add(b);
l.Add(a);
l.Sort();

Вышеприведенный сбой, хотя с InvalidOperationException. Может кто-нибудь объяснить, почему этот вид не работает, когда дочерний класс реализует интерфейс IComparable, или, по крайней мере, мне кажется, что это так.

Хорошо, вот моя реализация CompareTo для моего фактического родительского класса

 public int CompareTo(IDType other)
 {
       return this.Name.ToString().CompareTo(other.ToString());
 }

Ответы [ 3 ]

6 голосов
/ 02 февраля 2009

Ваш тип реализует IComparable<Parent> вместо IComparable<Child>. Как говорят документы MSDN для Sort , он будет выдавать InvalidOperationException, если "по сравнению с компаратором по умолчанию Comparer (T) .Default не может найти реализацию универсального интерфейса IComparable (T) или интерфейса IComparable для типа T" И действительно, это не может быть, где T - Ребенок. Если вы попытаетесь сделать это List<Parent>, вы вполне можете найти, что все в порядке.

РЕДАКТИРОВАТЬ: В качестве альтернативы (и предпочтительно, IMO) реализовать IComparable<Child>. На данный момент совсем не ясно, что ребенка можно разумно сравнить с другим ребенком. Реализация IComparable<Child> - даже если эта реализация откладывается до базовой реализации - объявляет о сопоставимости.

3 голосов
/ 02 февраля 2009

Я предполагаю, что это как-то связано с ковариацией / контравариантностью. Причина, по которой я это говорю, заключается в том, что это не так, как вы сказали:

 public class Parent : IComparable<Parent>
    {
        public int Age { get; set; }


        public int CompareTo(Parent other)
        {

            return this.Age.CompareTo(other.Age);
        }

    }

    public class Child : Parent
    {
        public string Name { get; set; }
    }

Однако, когда я изменил родителя для реализации не универсального IComparable и сделал это, он работал:

    public class Parent : IComparable
    {
    public int Age { get; set; }


    public int CompareTo(object other)
    {
        Parent p = other as Parent;
        return this.Age.CompareTo(p.Age);
    }

}

    public class Child : Parent
    {
        public string Name { get; set; }
    }

Код, с которым я тестировал:

    List<Child> c = new List<Child>();
    c.Add(new Child { Age = 10, Name = "Alex" });
    c.Add(new Child { Age = 6, Name = "Jack" });
    c.Add(new Child { Age = 15, Name = "Bob" });

    c.Sort();
3 голосов
/ 02 февраля 2009

Я попробовал и столкнулся с той же ошибкой. Я предполагаю, что, поскольку у вас есть List<Child>, он ищет кого-то, кто реализует IComparable<Child>, а не IComparable<Parent>.

Если изменить коллекцию на List<Parent>, кажется, что все работает. Или же, пусть Child реализует IComparable<Child> (и он может просто делегировать реализацию Parent).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...