Reputation: 717
When building lookup tables that exceed a single dimension I find myself nesting dictionaries a lot:
public class MyLookupTable
{
IDictionary<T1, IDictionary<T2, ISet<T3>>> mapOfMapOfSequences;
// Update the table
public void AddItem(T3 myItem);
// Access the table
public IEnumerable<T3> GetItems(T1 key1, T2 key2);
}
This has been working great for me so far, despite needing to write some wordy ContainsKey conditionals to access/modify the table.
Recently I am writing a caching mechanism that has 5 keys, and the dictionary field definition is a little ridiculous.
Architecturally, is there a design pattern I am completely overlooking that would make this problem a little more manageable?
Upvotes: 1
Views: 598
Reputation: 112259
ValueTuples
are helpful in creating ad-hoc types for scenarios like yours.
You could declare a dictionary like this:
IDictionary<(T1, T2, T3, T4, T5), TValue> dictionary;
Add values like this
dictionary.Add((k1, k2, k3, k4, k5), value);
You can find and example in the article Dissecting the tuples in C# 7 (MSDN).
You can also name the tuple items
IDictionary<(T1 key1, T2 key2, T3 key3, T4 key4, T5 key5), TValue> dictionary;
dictionary.Add((key1: k1, key2: k2, key3: k3, key4: k4, key5: k5), value);
Of course, you would choose speaking names adapted to your problem. Given a key, you can then access the tuple items like this:
var key = dictionary.Keys.First();
T3 k3 = key.key3;
or deconstruct the key with
var (k1, k2, k3, k4, k5) = dictionary.Keys.First();
Console.WriteLine($"Key 3 is {k3}");
C# 9 introduced record types
ValueTuples are good to be used locally; however, they are anonymous. If you want to expose a type in an API, then record classes or record structs are a better solution.
The C# compiler automatically creates the infrastructure required for dictionary keys. Among other things, it overrides Equals
and GetHashCode
and makes the record immutable.
All you need to write is something like this:
public readonly record struct MyKey(T1 Key1, T2 Key2, T3 Key3);
This creates a so called primary constructor with these 3 parameters as well as the whole body of the struct including 3 Key properties.
Upvotes: 2