Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with CompareTo

I am trying to implement a sorted list. I have created the class I want to have stored in the list, but for some reason when I try and run the sort the sort method I get an exception thrown. It appears something behind the scenes is passing in a null reference into the CompareTo method I have implemented.

Here’s what I believe to be relevant code.

Data object is defined like this:

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;
        }
    }
}
}

And the class to hold the list is defined like this:

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);

        }

    }
}

Here is the program I use to do the testing:

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();

The output of the test program is:

 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

Then it seems to pass a null rhs object into the compare method and I get a NullReferenceException when it tries to access the priority of rhs.

Can you tell me why this is happening and what I have to do to address this?

Please let me know if you need any more information.

like image 384
user589195 Avatar asked Jan 20 '23 17:01

user589195


1 Answers

When I run your code, I get an InvalidOperationException because CompareTo is not implemented correctly.

Your CompareTo implementation must return 0 if rhs is the same as this (i.e., this object and the object being compared are equal). It also should not fail if rhs == null, but should order null in a consistent way; this is typically done by always returning 1 to sort null before all valid objects.

The documentation for IComparable.CompareTo lists the following rules, which must be followed in order for Sort to function correctly:

  • A.CompareTo(A) is required to return zero.

  • If A.CompareTo(B) returns zero, then B.CompareTo(A) is required to return zero.

  • If A.CompareTo(B) returns zero and B.CompareTo(C) returns zero, then A.CompareTo(C) is required to return zero.

  • If A.CompareTo(B) returns a value other than zero, then B.CompareTo(A) is required to return a value of the opposite sign.

  • If A.CompareTo(B) returns a value x that is not equal to zero, and B.CompareTo(C) returns a value y of the same sign as x, then A.CompareTo(C) is required to return a value of the same sign as x and y.

To fix the problem, ensure that your implementation of CompareTo returns 0 when priority == rhs.priority && submitted == rhs.submitted.

like image 200
Bradley Grainger Avatar answered Jan 31 '23 07:01

Bradley Grainger