Dictionaries in .NET are expected to have close to O(1) lookup times. To achieve this, they make use of the GetHashCode() and Equals() methods of the key objects. The resulting hash code is used to divide the dictionary's contents into partitions. When you look up an item, the partition is identified using the hash code, all the items in that partition with a matching hash code* are compared to the key you're looking up using the Equals() method.
Here you are trying to create a dictionary with two keys for every object. You're doing this using a Tuple to make one key. The GetHashCode() result of a Tuple is based on both of its values, so the performance of a dictionary is lost if you want to look up values by only half of the key. You would need to go through the entire dictionary comparing each individual item, rendering it little better than a list.
One solution would be to make a dictionary that has a string->int key lookup, and then the other dictionary just be int->string. This would require two lookups when using string keys, but might be a good solution.
Example:
Dictionary<string, int> stringKeyToIntKey = new Dictionary<string, int>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();
intKeyDict[1] = "Test";
stringKeyToIntKey["I1"] = 1;
Console.WriteLine(intKeyDict[1]);
Console.WriteLine(intKeyDict[stringKeyToIntKey["I1"]]);
An add method could look like this:
public void AddEntry(int intKey, string stringKey, string value)
{
intKeyDict[intKey] = value;
stringKeyToIntKey[stringKey] = intKey;
}
And you could wrap TryGetValue to make life easier:
public bool TryGetValue(string stringKey, out string value)
{
value = null;
return stringKeyToIntKey.TryGetValue(stringKey, out int intKey) && intKeyDict.TryGetValue(intKey, out value);
}
Delete would look like this:
public void DeleteEntry(string stringKey)
{
if (stringKeyToIntKey.TryGetValue(stringKey, out int intKey))
{
intKeyDict.Remove(intKey);
stringKeyToIntKey.Remove(stringKey);
}
}
You would have to make sure that items are added and removed from both dictionaries at the same time. When you add an item to intKey, you would need to add the corresponding key mapping to stringKeyToIntKey.
Alternatively, you could have two dictionaries: one with a string key and one with an int key, and each would have the same values. Again you would have to add and remove items at the same time, and you would also have to update the values in both at the same time.
Example:
Dictionary<string, string> stringKeyDict = new Dictionary<string, string>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();
stringKeyDict["I1"] = "hello";
intKeyDict[1] = "hello";
Console.WriteLine(stringKeyDict["I1"]);
Console.WriteLine(intKeyDict[1]);
This is my favoured approach where the values are class instances, since both dictionaries will reference the same class instances for my items, and thus changes to properties of those instances will be reflected in both. For strings, however, the first option might be better.
* Hash codes are not unique and multiple objects can potentially have the same hash code, even if their values are not the same