i have the following problem and I cannot figure out where it comes from. I would appreciate help very much.
The code:
List<Point> lst = new List<Point>();
lst.Add(new Point(0, -2));
lst.Add(new Point(-1, -2));
lst.Sort(delegate (Point x,Point y)
{
if (x.X == 0)
return -1;
else if (y.X == 0)
开发者_StackOverflow社区 return 1;
else
{
double retVal1 = x.Y * 1.0 / -x.X;
double retVal2 = y.Y * 1.0 / -y.X;
int retVal = -Math.Sign(retVal1 - retVal2);
return retVal;
}
});
If executed, I recieve an ArgumentException saying that IComparer doesn't not return 0(null). However, it actually cannot return anything else but -1, 0 and 1, or?
Thank you very much for your help!
Ah, btw i'm using .NET 3.5
Actually the error message says: IComparer (or the IComparable methods it relies upon) did not return zero when Array.Sort called x. CompareTo(x). x: '' x's type: 'Point' The IComparer: 'System.Array+FunctorComparer`1[System.Drawing.Point]'.
You must return 0 if the objects are identical:
lst.Sort(delegate(Point x, Point y) {
if (x.X == y.X && x.Y == y.Y) { // you are missing this
return 0;
}
if (x.X == 0)
return -1;
else if (y.X == 0)
return 1;
else {
double retVal1 = x.Y * 1.0 / -x.X;
double retVal2 = y.Y * 1.0 / -y.X;
int retVal = -Math.Sign(retVal1 - retVal2);
return retVal;
}
});
You haven't completely read the Exception-Message. It most likely says that it does not return 0 for the same instance of the object.
Your code is wrong, if the same instance of Point
or an identical value is passed in, it needs to return 0
. Otherwise he would never know when he's done with sorting and would end up in an endless loop...and we all know that this is an absolute negative performance hit.
As said, a comparer must return 0 for the the same value as identity entails equality (something is always equal to itself) and equality entails equivalence (you may order two different things equivalently, but you must order two equal things equivalently).
There is a further problem, in that your check for .X being 0 could result in the same items returning inconsistent ordering if they both have .X equal to 0. It's an important rule that a comparison method must always be consistent in that:
If x < y then y > x.
If x < y and y < z then x < z.
Your algorithm breaks the first rule as thus:
Say point a is {0, 3} and point b is {0, 2}
Calling with (a, b) then returns -1 meaning a < b, but calling with (b, a) returns -1 meaning b < a.
Replace the whole thing with:
lst.Sort(delegate (Point x,Point y)
{
return (x.Y * 1.0 / -x.X).CompareTo(y.Y * 1.0 / -y.X);
});
(Note that this implicitly returns 0 for equal points - we could add an explicit check if this was a heavier calculation as an optimisation, but it isn't necessary.
Also, is Point
here System.Drawing.Point
? If so then this code is now fine, but if it's something else then it's worth noting that the code is fine if Point
is a struct, but should contain a null check if Point
is a class.
精彩评论