1

I am having some problem using SortedList in C# (I am working on Unity 5.0.3 with Visual Studio 2015). I have two classes ScoreKey and Score. ScoreKey implements IComparable.

But when I try to add entry to the SortedList I get the error

ArgumentException: element already exists
System.Collections.Generic.SortedList`2[ScoreKey,Score].PutImpl (.ScoreKey key, .Score value, Boolean overwrite)

I can't figure out why I am getting this error. I am using instances of an class as key so there is no chance of having the same key, right? Here is the code.

Class Definitions:

public class ScoreKey : IComparable
{
    public uint val;
    public uint timestamp;
    public int CompareTo(object obj)
    {
        ScoreKey s2 = obj as ScoreKey;
        if (s2.val == val)
        {
            return timestamp.CompareTo(s2.timestamp);
        }
        return val.CompareTo(s2.val);
    }
}
[System.Serializable]
public class Score
{

    public ScoreKey key;
    public uint val
    {
        get { return key.val; }
    }
    string user;
    public uint timestamp
    {
        get
        {
            return key.timestamp;
        }
    }
    public Score(string _user, uint _score)
    {
        key = new ScoreKey();
        key.timestamp = GetUTCTime();
        user = _user;
        key.val = _score;
    }
}

Test Code:

SortedList<ScoreKey, Score> scoreList = new SortedList<ScoreKey, Score>();
Score[] scores = {
    new Score("Bishal", 230),
    new Score("Bishal", 3456),
    new Score("Bishal", 230),
    new Score("Bishal", 123),
    new Score("Bishal", 86),
    new Score("Bishal", 4221)
};
for(int i = 0; i< scores.Length; i++)
{
    Debug.Log(scores[i].pretty);

    scoreList.Add(scores[i].key, scores[i]);
}

EDIT:

**GetUTCTime Function: **

public static uint GetUTCTime()
{
   return (uint)(System.DateTime.UtcNow.Subtract(new System.DateTime(1970, 1, 1))).TotalSeconds;
}
bytestorm
  • 1,201
  • 3
  • 17
  • 35

1 Answers1

1

I don't know what does GetUTCTime method do, but, assuming that it returns some measure of the current time, there is a high possibility that it returns the same value a few times in a row.

Thus you will have a duplicate key, because second field val is 230 in two elements:

new Score("Bishal", 230),
new Score("Bishal", 3456),
new Score("Bishal", 230),

If you wan't to generate unique timestamp like keys you can check How to ensure a timestamp is always unique?.

Community
  • 1
  • 1
Eugene Podskal
  • 9,882
  • 5
  • 29
  • 51
  • I added the getutctime method definition. And val will not be 0 check the constructor of Score class – bytestorm Feb 21 '16 at 14:45
  • Also In the current example timestamps will not be checked as none of the scores are equal – bytestorm Feb 21 '16 at 14:46
  • 1
    @bytestorm Since when is 230 not equal to 230? And since you are converting the timestamp to an integer value, if two objects are created withing the same second, they will have the same timestamp. – Dennis_E Feb 21 '16 at 14:48
  • @Dennis_E oh sorry that was the problem. My bad. – bytestorm Feb 21 '16 at 14:50
  • Yes, I need to make the timestamps unique. That should solve the rest of the problems. – bytestorm Feb 21 '16 at 14:52