Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. List<T>.Sort(IComparer) throws ArgumentException

List<T>.Sort(IComparer) throws ArgumentException

Scheduled Pinned Locked Moved C#
csharpjavajavascriptphpdatabase
7 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Firo Atrum Ventus
    wrote on last edited by
    #1

    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

    P L B 3 Replies Last reply
    0
    • F Firo Atrum Ventus

      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

      P Offline
      P Offline
      PIEBALDconsult
      wrote on last edited by
      #2

      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[^]

      F 1 Reply Last reply
      0
      • P PIEBALDconsult

        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[^]

        F Offline
        F Offline
        Firo Atrum Ventus
        wrote on last edited by
        #3

        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

        1 Reply Last reply
        0
        • F Firo Atrum Ventus

          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

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          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 and Y<Z might not imply X<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

          F 1 Reply Last reply
          0
          • F Firo Atrum Ventus

            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

            B Offline
            B Offline
            BobJanova
            wrote on last edited by
            #5

            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.

            F 1 Reply Last reply
            0
            • L Luc Pattyn

              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 and Y<Z might not imply X<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

              F Offline
              F Offline
              Firo Atrum Ventus
              wrote on last edited by
              #6

              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

              1 Reply Last reply
              0
              • B BobJanova

                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.

                F Offline
                F Offline
                Firo Atrum Ventus
                wrote on last edited by
                #7

                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

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups