SortedList does not remove and adding items correctly

I encountered a problem with SortedList where 2 methods give 2 diffrent results.

//Item Data is one of this sortedList item
var itemPos = Items.IndexOfValue(ItemData);
Item item;
Items.TryGetValue(itemPos, out item);

The result is not that obvious. I will operate on numbers rather on abstracts letters to better ilustrate what is happening.

itemPos is getting set to 5. Ok! Next we try to get this item again form this index but no. It returns null. Ofcourse this is not happening immediately. This code is called before that happens.

    public void MoveItem(int indexFrom, int indexWhere)
    {
        Item itemToSawp;
        Items.TryGetValue(indexFrom, out itemToSawp);
        Items.Remove(indexFrom);
        Items.Add(indexWhere, itemToSawp);
    }

To move items on sorted list we have to remove and add item again. Ok! Debugging says that operation went wonderfully and my item have now index 5 i moved it from index 4. Where index 5 were empty before method MoveItem.

Or was it empty? Before that operation i had index 5 filled with stuff and i called simple Items.Remove(5);

But now happens what i described before.

Worth noting that this only is happening when i move item upwards in index, look from 4-5. When i move from 5-4 everything works correctly.

Do you have any idea what is going on over here? I'm using .NET 3.5

Full code

using System;
using System.Collections.Generic;

class Program
{
    static SortedList<int, ItemData> Items = new SortedList<int, ItemData>();

    static void Main(string[] args)
    {
        var Foo = new ItemData();
        Items.Add(0, Foo);
        Items.Add(1, new ItemData());
        Items.Remove(1);
        MoveItem(0, 1);
        var itemPos = Items.IndexOfValue(Foo);
        Console.WriteLine(itemPos);
        //Console should return 1 i think
        ItemData item;
        Items.TryGetValue(itemPos, out item);
    }

    public static void MoveItem(int indexFrom, int indexWhere)
    {
        ItemData itemToSawp;
        Items.TryGetValue(indexFrom, out itemToSawp);
        Items.Remove(indexFrom);
        Items.Add(indexWhere, itemToSawp);
    }

    class ItemData
    {

    }
}

EDIT: This is a bit confusing, but! Indexer (look at name of it :P) Take as argument KEY not INDEX. This is what get me confused and i mixedup everythig. So as Christoph said. Its better to use you own list you could use it as desire or read documentation deeply.

Jon Skeet
people
quotationmark

You're confused between the key of the entry and the index of the entry. Your MoveItem method just changes the key associated with a value (by removing the old entry and creating a new entry). After these lines:

Items.Add(0, Foo);
Items.Add(1, new ItemData());
Items.Remove(1);

... there will only be a single entry in the collection, and MoveItem will remove/add so that doesn't change the count. Therefore IndexOfValue can only return 0 (or -1 if it's not found).

To get 1, you'd want to find the key associated with the value, not the index. For example:

int index = Items.IndexOfValue(Foo);
int key = Items.Keys[index];
Console.WriteLine("Key = {0}", key); // Prints 1

Note that TryGetValue takes the key, not the index - so this line:

Items.TryGetValue(itemPos, out item);

... would be a very odd one.

All of this is easier to see if you use a different key type, e.g. a string. Then you can't get confused between keys and indexes, because the types are different and the compiler won't let you use one where you meant the other.

people

See more on this question at Stackoverflow