C# - Tuple or other multikey variant for Dictionary, but with permutability


I am scratching my head over the following problem. I want to create a dictionary, which uses multiple keys. I came along the solutions suggesting tuples as the method of choice. I think this i a good way to go. However my problem has the following speciality. I would like to make the keys "permutable" (Sorry, if I am using the wrong slang here). What I mean with this, is the following. I want the result of dict[<key1,key2> to be the same as with dict[<key2,<key1>], because the data that I want to store is invariant to the order of keys.

As an example see the following code, which of course does at the moment not yield the result I am hoping for. I want the result with permuted key to be the same as for the key-tuple.

Tuple<string, string> key = new Tuple<string, string>("Name1", "Name2"); Dictionary<Tuple<string,string>, double> dict = new Dictionary<Tuple<string, string>, double>(); dict.Add(key, 5.0); Console.WriteLine(dict[key]); Tuple<string, string> permutedKey = new Tuple<string, string>("Name2", "Name1"); Console.WriteLine(dict[permutedKey]);

The reason for all this, I have to store data, which has to be indexed with two keys, but is essentially always symetrical. So there is no need, to store it two times.


You can define your own custom equality comparer and use it in the dictionary:

class TupleComparer<T> : IEqualityComparer<Tuple<T, T>> { public bool Equals(Tuple<T, T> x, Tuple<T, T> y) { return object.Equals(x.Item1, y.Item1) && object.Equals(x.Item2, y.Item2) || object.Equals(x.Item1, y.Item2) && object.Equals(x.Item2, y.Item1); } public int GetHashCode(Tuple<T, T> obj) { return obj.Item1.GetHashCode() + obj.Item2.GetHashCode(); } }

Then, you can create the dictionary passing it an instance of the comparer:

Tuple<string, string> key = new Tuple<string, string>("Name1", "Name2"); Dictionary<Tuple<string,string>, double> dict = new Dictionary<Tuple<string, string>, double>(new TupleComparer<string>()); dict.Add(key, 5.0); Console.WriteLine(dict[key]); var permutedKey = new Tuple<string, string>("Name2", "Name1"); Console.WriteLine(dict[permutedKey]);


You will need to define your own class with two elements and implement IComparable where CompareTo will be written as per you requirement. Then use that class as Key for your Dictionary. Also, please override method GetHashCode too.


Is comparing List<string> a viable option for your use case? If so, I'd recommend this stack overflow anser:

<a href="https://stackoverflow.com/questions/3669970/compare-two-listt-objects-for-equality-ignoring-order" rel="nofollow">Compare two List<T> objects for equality, ignoring order</a>

If you can't use List<string>, then I'd agree with rbaghbanli's answer.


  • How to simulate held down keys with VB.NET or C#?
  • how to check if a contour is an ellipse?
  • What data can I save in my database to verify a user with Google sign in API?
  • Identifying equivalent varargs function calls for memoization in Python
  • For a np.array([1, 2, 3]) why is the shape (3,) instead of (3,1)? [duplicate]
  • How to get attributes from parent?
  • Using CUDA 8.0 with GCC 6.x - bad function overloading complaint
  • Does c# have a rspec like testing framework that makes grouping like tests together?
  • Change day number color on click - not background
  • Hibernate UserType and a defined length
  • Optional parameter in UriTemplate in WCF
  • Shut down the underlying Executor of ExecutorCoroutineDispatcher
  • SQL Server Integrated Security from an Azure Web Site
  • Einsum optimize fails for basic operation
  • Invoking a controller's action by button in View without redirecting to any view
  • Cannot convert a char value to money. The char value has incorrect syntax
  • Is there a chance to get -splash: work for SWT applications that require -XstartOnFirstThread?
  • Cassandra: What is a subcolumn
  • Furthest-point Voronoi diagram in Java
  • OpenCV Python: Draw minAreaRect ( RotatedRect not implemented)
  • Counting Treaps
  • Problems with matplotlib.pyplot.xticks()
  • include dlls in visual studio c++ 2008
  • Merge Module leaving files during uninstall
  • How to convert integer to string and get length of string
  • R Split data.frame using a column that represents and on/off switch
  • Redirect STDERR in OPEN pipe comand. Perl Linux
  • How can I extract results of aggregate queries in slick?
  • Breeze - Deleted Items nav properties bug
  • Why value captured by reference in lambda is broken? [duplicate]
  • How do I change content of ComboFieldEditor?
  • javaw.exe and eclipse startup problems
  • Weird JavaScript statement, what does it mean?
  • Do I've to free mysql result after storing it?
  • SQL merge duplicate rows and join values that are different
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • Why joiner is not used after Sequence generator or Update statergy
  • need help with bizarre java.net.HttpURLConnection behavior
  • Recursive/Hierarchical Query Using Postgres
  • UserPrincipal.Current returns apppool on IIS