Проблема с CompareTo - PullRequest
       47

Проблема с CompareTo

4 голосов
/ 16 мая 2011

Я пытаюсь реализовать отсортированный список.Я создал класс, который хочу сохранить в списке, но по какой-то причине при попытке запустить метод сортировки я получаю исключение.Похоже, что что-то за кадром передает ссылку null в метод CompareTo, который я реализовал.

Вот что я считаю релевантным кодом.

Объект данных определяется следующим образом:

namespace PrioritisedRequestQueue
{
public class XactTask : IComparable<XactTask>
{
    public int priority;
    public DateTime submitted;
    public string name;

    public XactTask( int priority, DateTime submitted, string name)
    {
        this.priority = priority;
        this.submitted = submitted;
        this.name = name;
    }

    public int CompareTo(XactTask rhs )
    {
        //EXCEPTION OCCURS HERE AFTER A NULL RHS HAS BEEN PASSED IN**
        Console.WriteLine("comparing " + rhs.priority+"to "+this.priority); 

        if (rhs.priority <= this.priority)
        {
            Console.WriteLine("Entered first if");
            Console.WriteLine("comparing " + rhs.submitted + "to " + 
                this.submitted);
            if (rhs.submitted <= this.submitted)
            {
                Console.WriteLine("Entered second if");
                return 1;
            }
            else
            {
                return -1;
            }
        }
        else
        {
            Console.WriteLine("In else");
            return -1;
        }
    }
}
}

И класс для хранения списка определяется следующим образом:

namespace PrioritisedRequestQueue
{
    public class Class1
    {
        public List<XactTask> tasks;

        public Class1()
        {
            tasks = new List<XactTask>();
        }

        public void sort()
        {
            tasks.Sort();
        }

        public void add(XactTask task)
        {
            tasks.Add(task);

        }

    }
}

Вот программа, которую я использую для тестирования:

PrioritisedRequestQueue.Class1 tester = new PrioritisedRequestQueue.Class1();

tester.add(new PrioritisedRequestQueue.XactTask(1, DateTime.Now, "test1"));
tester.add(new PrioritisedRequestQueue.XactTask(1, DateTime.Now, "test2"));
Console.WriteLine(tester.tasks[0].name);
Console.WriteLine(tester.tasks[1].name);
tester.tasks.Sort();

Вывод тестовой программы:

 comparing 1to 1 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if
 comparing 1to 1 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if
 comparing 1to 1 
 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if
 comparing 1to 1 
 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if

Тогда, похоже, прошлоnull rhs объект в методе сравнения, и я получаю NullReferenceException, когда он пытается получить доступ к приоритету rhs.

Можете ли вы сказать мне, почему это происходит, и что я должен сделать, чтобы решить эту проблему?

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

1 Ответ

9 голосов
/ 16 мая 2011

Когда я запускаю ваш код, я получаю InvalidOperationException, потому что CompareTo не реализован правильно.

Ваша CompareTo реализация должна вернуть 0, если rhsсовпадает с this (т. е. этот объект и сравниваемый объект равны).Он также не должен потерпеть неудачу, если rhs == null, но должен упорядочить null согласованным образом;Обычно это делается путем возврата 1 для сортировки null перед всеми действительными объектами.

В документации для IComparable.CompareTo перечислены следующие правила, которые должны соблюдаться для того, чтобыДля правильной работы сортировки:

  • A.CompareTo(A) требуется для возврата нуля.

  • Если A.CompareTo(B) возвращает ноль, то B.CompareTo(A)требуется вернуть ноль.

  • Если A.CompareTo(B) возвращает ноль, а B.CompareTo(C) возвращает ноль, то A.CompareTo(C) требуется для возврата ноля.

  • Если A.CompareTo(B) возвращает значение, отличное от нуля, то B.CompareTo(A) требуется для возврата значения противоположного знака.

  • Если A.CompareTo(B) возвращает значение x, равноене равно нулю, и B.CompareTo(C) возвращает значение y того же знака, что и x, тогда A.CompareTo(C) требуется для возврата значения того же знака, что и x и y.

Чтобы устранить проблему, убедитесь, что ваша реализация CompareTo возвращает 0, когда priority == rhs.priority && submitted == rhs.submitted.

...