Why do I get a System.ArgumentException when invoking Sort(IComparer) on a List?

16,451

The problem is your implementation of your IComparer. It can return inconsistent results, so the sort function will throw an exception.

Maybe have a look at this and this question for more information.

Question:

Are the properties continent.Economy.CurrentDemand and continent.Economy.CurrentPrice free of side effects?

Remarks:

Your IComparer should be able to handle null. From the docs:

Comparing null with any type is allowed and does not generate an exception when using IComparable. When sorting, null is considered to be less than any other object.

Maybe it is an floating point issue, but that's just a wild guess. So maybe you should use decimal instead of float.

Share:
16,451
salocinx
Author by

salocinx

Updated on July 29, 2022

Comments

  • salocinx
    salocinx almost 2 years

    I sort a List with my own IComparer and this works just fine when running the application (XNA game) for more than an hour. But then, suddenly, I sometimes get the following error when invoking the sort-method with my custom Comparer:

    An unhandled exception of type 'System.ArgumentException' occured in mscorlib.dll
    Additional Information: ArgumentException
    

    This is the line where the exception is thrown:

    List<Continent> markets = new List<Continent>();
    // filling the markets list ...
    markets.Sort(new MarketCostCoverComparer(this)); 
    

    and this is my class implementing IComparer interface:

    class MarketCostCoverComparer : IComparer<Continent> { 
    
        private Player player; 
    
        public MarketCostCoverComparer(Player player) { 
            this.player=player; 
        } 
    
        public int Compare(Continent c1, Continent c2) { 
            if(player.GetCostCovering(c1)<player.GetCostCovering(c2)) { 
                return +1; 
            } else if(player.GetCostCovering(c1)==player.GetCostCovering(c2)) { 
                return 0; 
            } else { 
                return -1; 
            } 
        } 
    
    } 
    

    Here some methods that are linked to the comparer...:

    public float GetCostCovering(Continent continent) {
            // cover<1 => bad | cover>1 => good
            if(GetOilfieldTheoreticOutput(continent.Type, true)<continent.Economy.CurrentDemand) {
                return ((float)((GetOilfieldTheoreticOutput(continent.Type, true)*continent.Economy.CurrentPrice)))/(float)GetOilfieldCosts(continent.Type, true);
            } else {
                return ((float)((continent.Economy.CurrentDemand*continent.Economy.CurrentPrice)))/(float)GetOilfieldCosts(continent.Type, true);
            }
        }
    
    public int GetOilfieldTheoreticOutput(ContinentType continent, bool drilled) {
            int total = 0;
            foreach(Oilfield oilfield in worldmap.Continents[(int)continent].Oilfields) {
                if(oilfield.Owner==this && oilfield.Drilled==drilled) {
                    total+=oilfield.TheoreticOutput;
                }
            }
            return total;
        }
    
    public int GetOilfieldCosts(ContinentType continent, bool drilled) {
            int total = 0;
            foreach(Oilfield oilfield in worldmap.Continents[(int)continent].Oilfields) {
                if(oilfield.Owner==this && oilfield.Drilled==drilled) {
                    total+=oilfield.Costs;
                }
            }
            return total;
        }
    

    Here the screenshot of the exception:

    An unhandled exception of type 'System.ArgumentException' occured in mscorlib.dll

    Here a closer look of the Locals/Stack-Trace (this is an old screenshot, but I will try to reproduce this exception within the next hours, so that I can expand the trace):

    enter image description here