sra
sra

Reputation: 23973

SortedSet and SortedList fails with different enums

The whole story; I have some KeyValuePairs that I need to store in a session and my primary goal is to keep it small. Therefore I don't have the option of using many different collection. While the key is a different enum value of of a different enum type the value is always just a enum value of the same enum type. I have chosen a HashTable for this approach which content look like this (just many more):

// The Key-Value-Pairs
{ EnumTypA.ValueA1, MyEnum.ValueA },
{ EnumTypB.ValueB1, MyEnum.ValueB },
{ EnumTypC.ValueC1, MyEnum.ValueA },
{ EnumTypA.ValueA2, MyEnum.ValueC },
{ EnumTypB.ValueB1, MyEnum.ValueC }

At most I am running contains on that HashTable but for sure I also need to fetch the value at some point and I need to loop through all elements. That all works fine but now I have a new requirement to keep the order I have added them to the HashTable -> BANG

A HashTable is a map and that is not possible!

Now I thought about using a SortedList<object, MyEnum> or to go with more Data but slightly faster lookups and use a SortedSet<object> in addition to the HashTable.

Content below has been edited

The SortedList is implemented as

SortedList<Enum, MyEnum> mySortedList = new SortedList<Enum, MyEnum>();

the SortedSet is implemented as

SortedSet<Enum> mySortedSet = new SortedSet<Enum>();

The described Key - Value - Pairs are added to the sorted list with

void AddPair(Enum key, MyEnum value)
{
    mySortedList.Add(key, value);
}

And for the SortedSett like this

void AddPair(Enum key)
{
    mySortedSet.Add(key);
}

Both are failing with the exception:

Object must be the same type as the enum

My question is: What goes wrong and how can I archive my goal?

Used Solution

I've decided to life with the downside of redundant data against slower lookups and decided to implement a List<Enum> which will retain the insert order parallel to my already existing HashTable.

In my case I just have about 50-150 Elements so I decided to benchmark the Hashtable against the List<KeyValuePair<object,object>>

Therefore I have create me the following helper to implement ContainsKey() to the List<KeyValuePair<object,object>>

static bool ContainsKey(this List<KeyValuePair<object, object>> list, object key)
{
    foreach (KeyValuePair<object, object> p in list)
    {
        if (p.Key.Equals(key))
            return true;
    }
    return false;
}

I inserted the same 100 Entries and checked randomly for one of ten different entries in a 300000 loop. And... the difference was tiny so I decided to go with the List<KeyValuePair<object,object>>

Upvotes: 2

Views: 1408

Answers (1)

Cheng Chen
Cheng Chen

Reputation: 43523

I think you should store your data in an instance of List<KeyValuePair<Enum, MyEnum>> or Dictionary<Enum, MyEnum>.

SortedSet and SortedList are generic, but your keys are EnumTypeA/EnumTypeB, you need to specify the generic T with their base class(System.Enum) like:

SortedList<Enum, MyEnum> sorted = new SortedList<Enum, MyEnum>();

EDIT

Why you got this exception

SortedList and SortedSet use a comparer inside to check if two keys are equal. Comparer<Enum>.Default will be used as the comparer if you didn't specify the comparer in the constructor. Unfortunately Comparer<Enum>.Default isn't implemented as you expected. It throws the exception if the two enums are not the same type.

How to resolve the problem

If you don't want to use a List<KeyValuePair<Enum, MyEnum>> and insist using SortedLIst, you need to specify a comparer to the constructor like this:

class EnumComparer : IComparer<Enum>
{
    public int Compare(Enum x, Enum y)
    {
        return x.GetHashCode() - y.GetHashCode();
    }
}

var sorted = new SortedList<Enum, MyEnum>(new EnumComparer());

Btw, I think you need to obtain the "inserting order"? If so, List<KeyValuePair<K,V>> is a better choice, because SortedSet will prevent duplicated items.

Upvotes: 3

Related Questions