I am trying to use an IComparer
to sort a list of Points. Here is the IComparer class:
public class CoordinatesBasedComparer : IComparer
{
p
If you're slow like me, the -1 and 1 can be difficult to reason about when using IComparer
. The way to think about it is when x
should go first, return -1. When y
should go first, return 1.
It can still get confusing if you have lots of fields to sort by. You can use an Enum
to make your comparison logic more readable than 1 and -1, then cast the result.
This example puts objects with the least amount of null fields in the front.
public class NullishObjectsToTheBackOfTheLine: IComparer
{
private enum Xy
{
X = -1,
Both = 0,
Y = 1
};
//the IComparer implementation wraps your readable code in an int cast.
public int Compare(ClassToCompare x, ClassToCompare y)
{
return (int) CompareXy(x, y);
}
private static Xy CompareXy(ClassToCompare x, ClassToCompare y)
{
if (x == null && y == null) return Xy.Both;
//put any nulls at the end of the list
if (x == null) return Xy.Y;
if (y == null) return Xy.X;
if (x.Country == y.Country && x.ProductId == y.ProductId) return Xy.Both;
//put the least amount of at the front
if (x.ProductId == null && x.Country == null) return Xy.Y;
if (y.ProductId == null && y.Country == null) return Xy.X;
//put the country values that are not nulls in front
if (x.Country != y.Country) return x.Country != null ? Xy.X : Xy.Y;
//if we got this far, one of these has a null product id and the other doesn't
return x.ProductId != null ? Xy.X : Xy.Y;
}
}
public class ClassToCompare
{
public string Country { get; set; }
public string ProductId { get; set; }
}