Iterating through dictionaries the better way

Akos Nagy
Mar 24, 2018

Using the right collection type at the right place is a challenging task. In my experience, most people just use List<T or Dictionary<TKey,TValue> most of the time, without thinking about other possibilities.

Now that's not to say that these two are not a good choice for a lot of different tasks. I use them myself very often — in fact, I think most of my collection related code uses List<T>, Dictionary<TKey,TValue> or HashSet<T>.

And now the reason for this post: I was assigned a simple task to write something where storing the data as key-value pairs just came naturally. I knew I wouldn't actually be searching for any data by key, I just needed to store these two aspects (the key and the value) of a single piece of data together. I was actually using the IEnumerable<KeyValuePair<TKey,TValue>> aspect of Dictionary<TKey,TValue>, rather then the IDictionary<TKey,TValue> aspect, but using List<KeyValuePair<TKey,TValue>> just felt weird. Plus that would not solve the problem I was about to face either.

So I used my dictionary for data storage, rather than lookup. And then, I wrote my first foreach, something like this (of course, not something like this; you know, contractual obligations and whatnot):

foreach (var personEntry in people)
{
   var ssn = personEntry.Key;
   var person = personEntry.Value;
   Console.WriteLine($"{ssn}: {person.Name}");
}

Of course, any programmer worth his salt would write something like this (I mean, writing just personEntry.Key does not really say that it's the ssn, right?). But it's a lot more code than I'd like to see. The paradox here is that I traded readability (adding those two extra lines of code for a reason that does not contribute to functionality) for readability (describing in a clear way what Key and Value actually represent).

And then, I had a piphany. Actually, it was THE piphany. I want to write something like this:

foreach (var (ssn, person) in people)
{
   Console.WriteLine($"{ssn}: {person.Name}");
}

And believe it or not, that's a valid statement in C# 7. Provided that the composing type of people supports tuple deconstruction.

Unfortunately KeyValuePair<TKey,TValue> does not have the appropriate method. But hey, no worries, we can create one as an extension method and that's also a valid Deconstruct method.

public static class KeyValuePairExtensions
{
  public static void Deconstruct<TKey,TValue>(
              this KeyValuePair<TKey,TValue> entry,
              out TKey key,
              out TValue value)
  {
     key = entry.Key;
     value = entry.Value;
  }
}

And then, just add a using to the namespace of this class (or to the class itself with using static), and then you can iterate through your dictionary with the fancy deconstructing syntax:

foreach (var (ssn, person) in people)
{
   Console.WriteLine($"{ssn}: {person.Name}");
}

How cool is that? :)

Akos Nagy
Posted in C#