List<T>.Sort(IComparer) throws ArgumentException
-
I have a List<> of
ShipSprite
(a struct). I need to "sort" that list very often. But every once in a while, it Throws this Exception:ArgumentException.Message:
IComparer (or the IComparable methods it relies upon) did not return zero when Array.Sort called x. CompareTo(x). x: '' x's type: 'ShipSprite' The IComparer: 'ChangeDBLOL.ShipSpriteComparer'.
Here is the code for the
IComparer.Compare
method:int IComparer<ShipSprite>.Compare(ShipSprite x, ShipSprite y) { if (!(x.Confirmed ^ y.Confirmed)) { if (x.State == y.State) { if (x.TA == y.TA) { if (x.Equals(y)) { return 0; //It's the same ShipSprite, return 0 } else { int res = Utils.r.Next(2) == 0 ? 1 : -1;//OK, It's safe, Random! return res; } } else { return x.TA.CompareTo(y.TA); } } else { return x.State.CompareTo(y.State); } } if (x.Confirmed) return -1; if (y.Confirmed) return 1; return 0x1Dead; }
Just to be clear, I use this code for testing:
List<ShipSprite> sort = new List<ShipSprite>(sprites); int k = 0; StringBuilder sb = new StringBuilder(); while (true) { sb.AppendLine((k++).ToString()); sort.Sort(new ShipSpriteComparer()); sb.AppendLine("~~~~~Result list~~~~~"); foreach (ShipSprite s in sort) { sb.AppendLine(s.ToString()); } }
What bugs me is that this exception only occurs once every 25~40 sort. Do you guys have any idea of what might be the problem?
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian
-
I have a List<> of
ShipSprite
(a struct). I need to "sort" that list very often. But every once in a while, it Throws this Exception:ArgumentException.Message:
IComparer (or the IComparable methods it relies upon) did not return zero when Array.Sort called x. CompareTo(x). x: '' x's type: 'ShipSprite' The IComparer: 'ChangeDBLOL.ShipSpriteComparer'.
Here is the code for the
IComparer.Compare
method:int IComparer<ShipSprite>.Compare(ShipSprite x, ShipSprite y) { if (!(x.Confirmed ^ y.Confirmed)) { if (x.State == y.State) { if (x.TA == y.TA) { if (x.Equals(y)) { return 0; //It's the same ShipSprite, return 0 } else { int res = Utils.r.Next(2) == 0 ? 1 : -1;//OK, It's safe, Random! return res; } } else { return x.TA.CompareTo(y.TA); } } else { return x.State.CompareTo(y.State); } } if (x.Confirmed) return -1; if (y.Confirmed) return 1; return 0x1Dead; }
Just to be clear, I use this code for testing:
List<ShipSprite> sort = new List<ShipSprite>(sprites); int k = 0; StringBuilder sb = new StringBuilder(); while (true) { sb.AppendLine((k++).ToString()); sort.Sort(new ShipSpriteComparer()); sb.AppendLine("~~~~~Result list~~~~~"); foreach (ShipSprite s in sort) { sb.AppendLine(s.ToString()); } }
What bugs me is that this exception only occurs once every 25~40 sort. Do you guys have any idea of what might be the problem?
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian
How does it get populated? Can you insert in such a way that it stays sorted and you don't need to sort it? Getting the index of an item in a sorted IList[^]
-
How does it get populated? Can you insert in such a way that it stays sorted and you don't need to sort it? Getting the index of an item in a sorted IList[^]
Well,This List is used in Genetic algorithm, so I need to "sort" it very often. Here's the rule for sort: 1. Confirmed ShipSprite goes first 2. Sort according ShipStates 3. If above return 0, sort based on TA 4. If above return 0, check if it's the same ShipSprite and return 0 if it's same (so that we don't get that error) 4b. Random any ShipSprite that doesn't fulfill above conditions.
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian came as my third language. My fourth language? I'm still creating it, I'll let you know when it's done! :-D
-
I have a List<> of
ShipSprite
(a struct). I need to "sort" that list very often. But every once in a while, it Throws this Exception:ArgumentException.Message:
IComparer (or the IComparable methods it relies upon) did not return zero when Array.Sort called x. CompareTo(x). x: '' x's type: 'ShipSprite' The IComparer: 'ChangeDBLOL.ShipSpriteComparer'.
Here is the code for the
IComparer.Compare
method:int IComparer<ShipSprite>.Compare(ShipSprite x, ShipSprite y) { if (!(x.Confirmed ^ y.Confirmed)) { if (x.State == y.State) { if (x.TA == y.TA) { if (x.Equals(y)) { return 0; //It's the same ShipSprite, return 0 } else { int res = Utils.r.Next(2) == 0 ? 1 : -1;//OK, It's safe, Random! return res; } } else { return x.TA.CompareTo(y.TA); } } else { return x.State.CompareTo(y.State); } } if (x.Confirmed) return -1; if (y.Confirmed) return 1; return 0x1Dead; }
Just to be clear, I use this code for testing:
List<ShipSprite> sort = new List<ShipSprite>(sprites); int k = 0; StringBuilder sb = new StringBuilder(); while (true) { sb.AppendLine((k++).ToString()); sort.Sort(new ShipSpriteComparer()); sb.AppendLine("~~~~~Result list~~~~~"); foreach (ShipSprite s in sort) { sb.AppendLine(s.ToString()); } }
What bugs me is that this exception only occurs once every 25~40 sort. Do you guys have any idea of what might be the problem?
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian
Hi, 1. I would write all that quite differently, see consecutive diff calculations under "composite sort criteria" in my article here[^]. 2. I don't like your random stuff a bit, and I guess neither does the sorting algorithm. It really wants IComparer(x,y) to be trustworthy, i.e. to ALWAYS return the same result. If you need some randomness, I think you should somehow store the result of the RNG and make sure you return consistent values (otherwise
X<Y
andY<Z
might not implyX<Z
, which would upset most everyone). [EDIT] The right thing to do for randomness would be like this: give your "objects" one more field, which you fill with random integer numbers beforehand; then use that field as the last sort criterion. [/EDIT] [ADDED] FWIW: If I were to need data sorted, the first thing I'd do is make them real objects (i.e. reference type), not structs. It would avoid all boxing/unboxing pitfalls and costs, and it most likely would sort faster as now only the pointers need being swapped, not the entire object values. [/ADDED] :)Luc Pattyn [My Articles] Nil Volentibus Arduum
-
I have a List<> of
ShipSprite
(a struct). I need to "sort" that list very often. But every once in a while, it Throws this Exception:ArgumentException.Message:
IComparer (or the IComparable methods it relies upon) did not return zero when Array.Sort called x. CompareTo(x). x: '' x's type: 'ShipSprite' The IComparer: 'ChangeDBLOL.ShipSpriteComparer'.
Here is the code for the
IComparer.Compare
method:int IComparer<ShipSprite>.Compare(ShipSprite x, ShipSprite y) { if (!(x.Confirmed ^ y.Confirmed)) { if (x.State == y.State) { if (x.TA == y.TA) { if (x.Equals(y)) { return 0; //It's the same ShipSprite, return 0 } else { int res = Utils.r.Next(2) == 0 ? 1 : -1;//OK, It's safe, Random! return res; } } else { return x.TA.CompareTo(y.TA); } } else { return x.State.CompareTo(y.State); } } if (x.Confirmed) return -1; if (y.Confirmed) return 1; return 0x1Dead; }
Just to be clear, I use this code for testing:
List<ShipSprite> sort = new List<ShipSprite>(sprites); int k = 0; StringBuilder sb = new StringBuilder(); while (true) { sb.AppendLine((k++).ToString()); sort.Sort(new ShipSpriteComparer()); sb.AppendLine("~~~~~Result list~~~~~"); foreach (ShipSprite s in sort) { sb.AppendLine(s.ToString()); } }
What bugs me is that this exception only occurs once every 25~40 sort. Do you guys have any idea of what might be the problem?
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian
A sort algorithm should always return consistent results, i.e. don't do the random thing. If two items are sort-order-equivalent, the comparison should return 0. Why are you doing that weird XOR check when it seems to be equivalent to [ if(x.Confirmed == y.Confirmed) ]? Not that I think that's responsible for the problem but it is needlessly confusing. What types are TA and State, and do they have comparators (or equality operator overrides) which could mess things up? Did you override Equals on ShipSprite, and if so did you do it correctly? As an aside, why is this a struct? It looks complex enough that it should be a class. Sorting a list of structs requires moving around and copying a lot more bits of memory.
-
Hi, 1. I would write all that quite differently, see consecutive diff calculations under "composite sort criteria" in my article here[^]. 2. I don't like your random stuff a bit, and I guess neither does the sorting algorithm. It really wants IComparer(x,y) to be trustworthy, i.e. to ALWAYS return the same result. If you need some randomness, I think you should somehow store the result of the RNG and make sure you return consistent values (otherwise
X<Y
andY<Z
might not implyX<Z
, which would upset most everyone). [EDIT] The right thing to do for randomness would be like this: give your "objects" one more field, which you fill with random integer numbers beforehand; then use that field as the last sort criterion. [/EDIT] [ADDED] FWIW: If I were to need data sorted, the first thing I'd do is make them real objects (i.e. reference type), not structs. It would avoid all boxing/unboxing pitfalls and costs, and it most likely would sort faster as now only the pointers need being swapped, not the entire object values. [/ADDED] :)Luc Pattyn [My Articles] Nil Volentibus Arduum
What confuses me is that the previous version works fine even with this "random sort" :laugh: Yeah, I'll try to add a field and fill it with random value before sort. Also, that struct is a gift from previous developer. ;P
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian came as my third language. My fourth language? I'm still creating it, I'll let you know when it's done! :-D
-
A sort algorithm should always return consistent results, i.e. don't do the random thing. If two items are sort-order-equivalent, the comparison should return 0. Why are you doing that weird XOR check when it seems to be equivalent to [ if(x.Confirmed == y.Confirmed) ]? Not that I think that's responsible for the problem but it is needlessly confusing. What types are TA and State, and do they have comparators (or equality operator overrides) which could mess things up? Did you override Equals on ShipSprite, and if so did you do it correctly? As an aside, why is this a struct? It looks complex enough that it should be a class. Sorting a list of structs requires moving around and copying a lot more bits of memory.
Well, TA is a DateTime and State is an int, so they shouldn't mess things up. I have also checked Equals on ShipSprite and it seems fine. I will do as Luc's suggestion, create a new field and fill it with random value before sorting. That XOR and struct is results of fluctuate requirement and management's motto "Previous developer did it fine this way, don't change it!"
Oxfords English < Official CCC Players Dictionary Excuse me for my improper grammar and typos. It's because English is my primary language, not my first language. My first languages are C# and Java. VB, ASP, JS, PHP and SQL are my second language. Indonesian came as my third language. My fourth language? I'm still creating it, I'll let you know when it's done! :-D