Icomparer and Nullable field

  • Thread starter Thread starter tshad
  • Start date Start date
T

tshad

Using VS 2005, I have list that I want to sort that has a nullable field.

I am getting an error:

'System.Nullable<int>' does not contain a definition for 'CompareTo'

I am getting an error on the "secondInstance test for ProjectTableID, which
is a nullable int (int?).

public class RacerComparer : IComparer<FieldName>
{
public int Compare(FieldName firstInstance, FieldName
secondInstance)
{
int result = 0;
result =
firstInstance.ProcessOrder.CompareTo(secondInstance.ProcessOrder);
if (result != 0) return (result); // if not equal, not need to
check Name
result =
secondInstance.ProjectTableID.CompareTo(secondInstance.ProjectTableID);
if (result != 0) return (result);
return result;
}
}

I can't even test for the null (HasValue), because I am getting the error on
the build.

How can I change this so that I don't get this error?

Thanks,

Tom
 
tshad said:
Using VS 2005, I have list that I want to sort that has a nullable field.

I am getting an error:

'System.Nullable<int>' does not contain a definition for 'CompareTo'

I am getting an error on the "secondInstance test for ProjectTableID, which
is a nullable int (int?).

public class RacerComparer : IComparer<FieldName>
{
public int Compare(FieldName firstInstance, FieldName
secondInstance)
{
int result = 0;
result =
firstInstance.ProcessOrder.CompareTo(secondInstance.ProcessOrder);
if (result != 0) return (result); // if not equal, not need to
check Name
result =
secondInstance.ProjectTableID.CompareTo(secondInstance.ProjectTableID);
if (result != 0) return (result);
return result;
}
}

I can't even test for the null (HasValue), because I am getting the error on
the build.

How can I change this so that I don't get this error?

I'd personally use Comparer<T>.Default. That handles nulls with no
problems.
 
tshad said:
Using VS 2005, I have list that I want to sort that has a nullable field.

I am getting an error:

'System.Nullable<int>' does not contain a definition for 'CompareTo'

I am getting an error on the "secondInstance test for ProjectTableID,
which is a nullable int (int?).

public class RacerComparer : IComparer<FieldName>
{
public int Compare(FieldName firstInstance, FieldName
secondInstance)
{
int result = 0;
result =
firstInstance.ProcessOrder.CompareTo(secondInstance.ProcessOrder);
if (result != 0) return (result); // if not equal, not need
to check Name
result =
secondInstance.ProjectTableID.CompareTo(secondInstance.ProjectTableID);
if (result != 0) return (result);
return result;
}
}

I can't even test for the null (HasValue), because I am getting the error
on the build.

How can I change this so that I don't get this error?

You need to test HasValue first and then if both have values, call
GetValueOrDefault() and compare the results.
 
Jon Skeet said:
I'd personally use Comparer<T>.Default. That handles nulls with no
problems.

I found the problem.

I had to change:

secondInstance.ProjectTableID.CompareTo(secondInstance.ProjectTableID);

to

secondInstance.ProjectTableID.Value.CompareTo(secondInstance.ProjectTableID.Value);

and it worked fine.

I am not sure how I would do this with the Comparer<T>.Default using the
multiple field sorts.

Thanks,

Tom
 
You could also use the "Nullable" static class, this calss makes it easy to
compare nullable values so that you don't have to worry about nulls.

int result = Nullable.Compare<int>(val1, val2);



tshad said:
Jon Skeet said:
I'd personally use Comparer<T>.Default. That handles nulls with no
problems.

I found the problem.

I had to change:

secondInstance.ProjectTableID.CompareTo(secondInstance.ProjectTableID);

to

secondInstance.ProjectTableID.Value.CompareTo(secondInstance.ProjectTableID.Value);

and it worked fine.

I am not sure how I would do this with the Comparer<T>.Default using the
multiple field sorts.

Thanks,

Tom
 
tshad said:
I found the problem.

I had to change:

secondInstance.ProjectTableID.CompareTo(secondInstance.ProjectTableID);

to

secondInstance.ProjectTableID.Value.CompareTo(secondInstance.ProjectTableID.Value);

and it worked fine.

I am not sure how I would do this with the Comparer<T>.Default using the
multiple field sorts.

I am not sure how to use Comparer<T>.Default. Especially with multiple
field sorts.

I did get my multipe field sort to work with:
public class Racer
{
private string name;
public string Name { get { return name; } }
private string car;
public string Car { get { return car; } }
public Racer(string name, string car)
{
this.name = name;
this.car = car;
}
public override string ToString()
{
return name + ", " + car;
}

}

public class RacerCollection : List<Racer> { }

public class FindRacer
{
private string car;
public FindRacer(string car)
{
this.car = car;
}
public bool DrivingCarPredicate(Racer racer)
{
return racer.Car == car;
}
}

public class RacerComparer : IComparer<Racer>
{
public int Compare(Racer firstInstance, Racer secondInstance)
{
int result = 0;
result = firstInstance.Car.CompareTo(secondInstance.Car);
if (result != 0) return (result); // if not equal, not need to
check Name
result = firstInstance.Name.CompareTo(secondInstance.Name);
if (result != 0) return (result);
return result;
}
}

I was having a little problems with understanding how the IComparer or the
delegate works and I think I have it now.

racers.Sort... will go through the list doing the CompareTo as many times as
it needs to until the list is sorted. I assume it just works like a foreach
loop in a Do until loop. Something like

do
{
foreach (Racer r in RacerCollection)
{
CompareTo(...)
}
}while( hadASwitch

If you are just going to do a simple sort with one of the properties in the
class there is no reason to use IComparer. You can just do the following
with a delegate for whichever property you want to sort the list with:

racers.Sort(delegate(Racer r1, Racer r2) { return
r1.Name.CompareTo(r2.Name); });
or
racers.Sort(delegate(Racer r1, Racer r2) { return
r1.Car.CompareTo(r2.Car); });

If you need to do something special, such as a multiple field sort then you
need to set up a separate class to handle each type of sort you may need to
do (such as my RacerComparer() method above) and just call it with no
parameters:

racers.Sort(new RacerComparer());

I think that is how it works.

Thanks,

Tom
Thanks,

Tom
 
I am not sure how to use Comparer<T>.Default. Especially with multiple
field sorts.

Doing multi-field sorts takes a little bit of work. I've got a class in
MiscUtil to make life a bit easier.
http://pobox.com/~skeet/csharp/miscutil
I was having a little problems with understanding how the IComparer or the
delegate works and I think I have it now.

racers.Sort... will go through the list doing the CompareTo as many times as
it needs to until the list is sorted. I assume it just works like a foreach
loop in a Do until loop. Something like

do
{
foreach (Racer r in RacerCollection)
{
CompareTo(...)
}
}while( hadASwitch

Well, not quite. It does whatever comparisons it needs, which depends
on the algorithm it uses.
If you are just going to do a simple sort with one of the properties in the
class there is no reason to use IComparer. You can just do the following
with a delegate for whichever property you want to sort the list with:

racers.Sort(delegate(Racer r1, Racer r2) { return
r1.Name.CompareTo(r2.Name); });
or
racers.Sort(delegate(Racer r1, Racer r2) { return
r1.Car.CompareTo(r2.Car); });

If you need to do something special, such as a multiple field sort then you
need to set up a separate class to handle each type of sort you may need to
do (such as my RacerComparer() method above) and just call it with no
parameters:

racers.Sort(new RacerComparer());

I think that is how it works.

Not really. You can do a multi-field sort with a Comparison delegate
too. You can build a delegate instance from the Compare method you've
already got.
 
Back
Top