4

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.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
user589195
  • 4,180
  • 13
  • 53
  • 81
  • 3
    @Uwe His question gives all the information requried, in a relatively concise and well formatted way. I don't think anything should be cut out, as it all looks relevant. – RB. May 16 '11 at 14:12
  • 1
    Are you sure it's a null ref exception? I could see a different exception being thrown – JaredPar May 16 '11 at 14:12
  • @user Please can you highlight exactly where the Exception occurs. It is not clear from your description. – RB. May 16 '11 at 14:14
  • 1
    @Uwe, if you did read the first paragraph you would see it states the problem Im having. The rest of the information is then provided to aid anyone that thinks they might be able to help. In my opinion it is far worse to have not enough information that too much. – user589195 May 16 '11 at 14:16
  • @RB If I do see horizontal scrollbars in source code fragments, my mind seems to just turn itself off :-). – Uwe Keim May 16 '11 at 14:20
  • @RB Thanks alot, it's much easier to read now :-) – Uwe Keim May 16 '11 at 14:53

1 Answers1

9

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.

Bradley Grainger
  • 27,458
  • 4
  • 91
  • 108