Reputation: 23973
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 aList<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 theList<KeyValuePair<object,object>>
Therefore I have create me the following helper to implement
ContainsKey()
to theList<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
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