Iterating through dictionaries the better way
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? :)