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.
When I run your code, I get an
InvalidOperationExceptionbecauseCompareTois not implemented correctly.Your
CompareToimplementation must return0ifrhsis the same asthis(i.e., this object and the object being compared are equal). It also should not fail ifrhs == null, but should ordernullin a consistent way; this is typically done by always returning1to sortnullbefore 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 returnzero.
If
A.CompareTo(B)returns zero, thenB.CompareTo(A)is required to returnzero.
If
A.CompareTo(B)returns zero andB.CompareTo(C)returns zero, thenA.CompareTo(C)is required to returnzero.
If
A.CompareTo(B)returns a valueother than zero, then
B.CompareTo(A)is required to return a value of the
opposite sign.
If
A.CompareTo(B)returns a value xthat is not equal to zero, and
B.CompareTo(C)returns a value y ofthe same sign as x, then
A.CompareTo(C)is required to returna value of the same sign as x and y.
To fix the problem, ensure that your implementation of
CompareToreturns 0 whenpriority == rhs.priority && submitted == rhs.submitted.