C# Linq Except: How to Get Items Not In Another List

Overview

When writing C# code we often want to do set based operations on Lists, Dictionaries or other IEnumerables. Here I’ll walk you through Except, a Linq extension method that you can use to get objects from one List that don’t exist in another. I’ll also explain how you can use the same approach on dictionaries and I’ll touch on other similar set based methods like Union, Concat and Intersect.

Except

To get the items from list one list (A) that are not in another list (B) you can use the Linq Except method like this:

var a = new List<int>() { 1, 2, 3, 4, 5 };
var b = new List<int>() { 2, 4, 9, 16, 25 };

var aNotB = a.Except(b);

aNotB.ToList().ForEach(x => Console.WriteLine(x));

Which will produce the following results:

1
3
5

Except is a Linq extension method, so to use it you must first import System.Linq at the top of your file, like this:

using System.Linq;

It’s worth bearing in mind that the result of A.Except(B) will be an IEnumerable, if you want the result as a list call .ToList() as I’ve done above.

Linq Except is the C# equivalent of using “Where X Not In” in SQL.

Except: Example Use Case

There are all sorts of reasons you might want the values from one list that aren’t in another, for instance:

Say you have a shopping list, but you’ve just been to the store and bought some of the items, you might want to get everything on the original shopping list that you didn’t just purchase:

var shopppingList = new List<string>()
{
    "apples",
    "beans",
    "pasta",
    "butter",
    "rice",
    "flour",
    "eggs"
};

var itemsBought = new List<string>()
{
    "chocolate",
    "butter",
    "flour",
    "eggs",
    "icing sugar"
};

var newShoppingList = shopppingList.Except(itemsBought);

Console.WriteLine("You still need to buy the following items:");
foreach (var item in newShoppingList)
{
    Console.WriteLine($"  {item}");
}

Which outputs:

You still need to buy the following items:
  apples
  beans
  pasta
  rice

Using Except with Dictionaries (i.e. Get Items Not In Another Dictionary)

Linq Except works for any IEnumerable, so it’s pretty easy to use it to check for items in one dictionary that are not in another dictionary by calling var aExceptB = a.Except(b); as follows:

var a = new Dictionary<int, int>()
{
    { 0, 0 },
    { 1, 1 },
    { 2, 4 },
    { 3, 9 },
    { 4, 16 }
};

var b = new Dictionary<int, int>()
{
    { 0, 0 },
    { 1, 2 },
    { 2, 4 },
    { 3, 6 }
};

var aExceptB = a.Except(b);

aExceptB.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
[1, 1]
[3, 9]
[4, 16]
*/

By default, this will consider items in the dictionary to match if (and only if) both their keys and values are equal. Eg. [apples, 6] will match [apples, 6] bit won’t match [apples, 4].

Although this is the default behaviour of a C# Dictionary Except, you often just want all the items from Dictionary A where the item’s key doesn’t exist in Dictionary B. You can do this kind of dictionary except as follows:

How to use except with a dictionary just comparing keys (i.e. Using a non-default IEqualityComparer)

One caveat when using Except on dictionaries is that for two items in a dictionary to be considered equal, both the key and the value must be equal. But what if you don’t care what the value is, you just want to compare using keys?

This is where it’s helpful to be able to specify what it means for two things to be equal. To do this we need to implement IEqualityComparer:

private class KeyComparer<T1, T2> : IEqualityComparer<KeyValuePair<T1, T2>>
    where T1 : IComparable
{
    public bool Equals(KeyValuePair<T1, T2> x, KeyValuePair<T1, T2> y)
    {
        //Check whether the keys are equal
        return x.Key.Equals(y.Key);
    }

    // GetHashCode() must return the same value for equal objects.
    public int GetHashCode(KeyValuePair<T1, T2> kVPair)
    {
        return kVPair.Key.GetHashCode();
    }
}

static void Main()
{
    var a = new Dictionary<int, int>()
    {
        { 0, 0 },
        { 1, 1 },
        { 2, 4 },
        { 3, 9 },
        { 4, 16 }
    };

    var b = new Dictionary<int, int>()
    {
        { 0, 0 },
        { 1, 2 },
        { 2, 4 },
        { 3, 6 }
    };

    var aExceptB = a.Except(b, new KeyComparer<int, int>());

    aExceptB.ToList().ForEach(x => Console.WriteLine(x));

    /* this code outputs:
    [4, 16]
    */
}

The important bit here is return x.Key.Equals(y.Key); this says that if if element X has the same key as element Y, then consider them to be equal. This means that { 3, 9 } in dictionary A can match with { 3, 6 } in Dictionary B because the keys of both match, hence it’s excluded from the output.

Other similar functions

Union

If you want any element that is in either list A or list B, then union might be the way to go:

var a = new List<int>() { 1, 2, 3, 4 };
var b = new List<int>() { 3, 4, 5, 6 };

var aUnionB = a.Union(b);

aUnionB.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
1
2
3
4
5
6
*/

However, implicitly does a Distinct on the results, so you won’t get repeated elements just because they’re in both lists. Moreover – I tried it with two 1s in list A and got the same results output – so be warned, this will remove duplicates from your lists.

If you want to keep the duplicates, consider Concat:

Concat

This is a lot like Union, but it will keep the duplicated results. A.Concat(B) will give you list A concatenated with (joined on to) list B. i.e. you’ll get all the elements in A and all the Elements in B, and any values in both will be duplicated. For example:

var a = new List<int>() { 1, 2, 3, 4 };
var b = new List<int>() { 3, 4, 5, 6 };

var results = a.Concat(b);

results.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
1
2
3
4
3
4
5
6
*/

You can see from the output that List b has simple been stuck on the end of List A.

Intersect

So you want the all the items that occur in both list a and list b? You’re looking for the Linq Intersect method. It can be used as follows:

var a = new List<int>() { 1, 2, 3, 3, 4 };
var b = new List<int>() { 3, 4, 5, 6 };

var aIntersectB = a.Intersect(b);

aIntersectB.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
3
4
*/

As you can see from the given results, this also does an implicit Distinct, so you will lose and duplicated values in your lists.

Not Intersect?

What if you want any items from list A that aren’t in B and any items from List B that aren’t in A? Well, there isn’t a dedicated Linq method exactly for that… but, you can build it up yourself with the Union and Except methods:

var a = new List<int>() { 1, 2, 3, 4 };
var b = new List<int>() { 3, 4, 5, 6 };

var results = a.Except(b).Union(b.Except(a));

results.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
1
2
5
6
*/

Distinct

I’ve mentioned distinct a few times and it’s worth a mention, but it’s slightly different to the methods so far discussed. So far we’ve looked at methods that take two IEnumerables and return an IEnumerable. Distinct is different in that it takes a single IEnumerable and returns an IEnumerable.

Distinct is used to return the distinct elements from a list, i.e. at most one copy of every element in a list. It can be used as follows:

var a = new List<int>() { 1, 2, 3, 3, 4, 1 };

var results = a.Distinct();

results.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
1
2
3
4
*/

Do These Linq Methods Preserve the Order of Elements?

I wasn’t sure, so I tried it, and yes, these Linq methods do preserve the order of the items in the Lists:

var a = new List<int>() {4, 3, 2, 4, 1 };
var b = new List<int>() { 3, 4, 5, 6 };

var results = a.Union(b);

results.ToList().ForEach(x => Console.WriteLine(x));

/* this code outputs:
4
3
2
1
5
6
*/

Conclusion

Hopefully this has given you a good introduction to performing set based operations in C# with Linq. In particular using Except to find the items in one list that aren’t in another.

If you’ve spotted a mistake, or if you think there’s something I could add to make this more useful, or if you just want to say “hi” then please leave a message in the comments.

Until next time, have a nice day.

C# Linq Group By

This is a favourite of mine, simply because it always used to trip me up. I put this down to learning SQL before Linq, so I expect Linq to behave the same way as SQL. As you’ll see below, when it comes to Group By they behave a little differently.

Linq Group By Example

private class Record
{
    public string Name { get; set; }
    public int Score { get; set; }
}

static void Main()
{
    var scores = new List<Record>()
    {
        new Record() { Name = "Bill", Score = 2 },
        new Record() { Name = "Ted", Score = 9 },
        new Record() { Name = "Bill", Score = 1 },
        new Record() { Name = "Ted", Score = 8 },
        new Record() { Name = "Bill", Score = 9 },
        new Record() { Name = "Ted", Score = 5 },
    };

    var groupings = scores.GroupBy(x => x.Name);

    foreach (var grouping in groupings)
    {
        Console.WriteLine(grouping.Key);
        foreach (var record in grouping)
        {
            Console.WriteLine($"  {record.Score}");
        }
    }
}

Which outputs:

Peter
  2
  1
  9
Ralph
  9
  8
  5

First we create a struct (Record) to hold our sample data and initialise list of Records with some data.

The actual linq group by statement is then done on line 19 and results in an object of type: IEnumerable<IGrouping<string, Record>> (which I called groupings). I then use a foreach (line 21) to iterate over each of these groupings, printing it’s name and each of it’s values (with another foreach on line 24).

What is Linq Group By used for?

Linq Group By is for grouping a set of results by a certain attribute. In the example above we’re grouping Score by the name on the score. But equally you could group accounting figures by month, sales figures by widget, people by age – the list is endless.

Quite often you’ll want to then summarise the data using an aggregation function, but as we’ll see below – with Linq Group By, you don’t have to!

What is an IGrouping?

The full definition of IGrouping can be found in the microsoft docs, and I would agree with them that an IGrouping represents a collection of objects that have a common key. But what actually is it?

Since .NET Core is now open source, we can see for ourselves by looking at the relevant source code:

public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>
{
    TKey Key { get; }
}

This shows us that an IGrouping is an IEnumerable with an additional Key property.

Does this make intuitive sense? I think so: the Group By statement divides an IEnumerable into smaller IEnumerables (IGroupings) and labels each of these with the key that they all share.

In the example above, we ended up with two IGroupings, each one holding the set of Records that shared a Name (so three Records for Bill and three for Ted). We could have worked out which group was which by looking at the first element in each and checking it’s Name, but the IGrouping’s key property was handy because meant we didn’t have to look into the records – the key is right there:

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    // Without using key property
    Console.WriteLine(group.First().Name);

    // Using IGroupings's key property
    Console.WriteLine(group.Key);
}

Common Use Case Examples

Usually when you’re grouping by something, you’re aiming to aggregate the results. This is so common, that in SQL you can’t group by without the aggregation step. The following examples show some different ways to aggregate the results of a Linq Group By:

Linq Group By Count

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.WriteLine(
        $"{group.Key}: {group.Count()}");
}

Here we use the same Group By to get our IEnumerable of IGroupings, but this time instead of printing the score from each Record, we use Linq Count to count the number of Records in the IGrouping instead. The above code outputs:

Bill: 3
Ted: 3

Linq Group By Sum

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.WriteLine(
        $"{group.Key}: {group.Sum(x => x.Score)}");
}

We use the same Group By statement as before, but now we print the sum of the Score of all the records in the IGrouping. This results in:

Bill: 12
Ted: 22

Linq Group By Average

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.WriteLine(
        $"{group.Key}: {group.Average(x => x.Score)}");
}

You might be starting to see a theme here. As before, we use Group By to get a set of IGroupings, then when print the average (mean) of the scores of all Records in the IGrouping. This results in:

Bill: 4
Ted: 7.33333333333333

Linq Group By Min

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.WriteLine(
        $"{group.Key}: {group.Min(x => x.Score)}");
}

As above, we use a Linq Group By to get a set (IEnumerable) of IGroupings, then for each IGrouping we print the minimum Score from all it’s Records. This results in:

Bill: 1
Ted: 5

Linq Group By Max

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.WriteLine(
        $"{group.Key}: {group.Max(x => x.Score)}");
}

As above, we use a Linq Group By to get a set (IEnumerable) of IGroupings, then for each IGrouping we print the max Score from all it’s Records using Linq Max. This results in:

Bill: 9
Ted: 9

C# Linq Group By Contains

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.Write($"Did {group.Key} ever score an 8? ");
    Console.WriteLine(group.Select(x => x.Score).Contains(8) ? "Yes" : "No");
}

This uses a slightly different pattern: We use the same Group By as before to get a set of IGroupings, we then use Select to convert each IGrouping to a set of scores, then we use Linq Contains on these scores to check if there’s an 8 in there. This code outputs:

Did Bill ever score an 8? No
Did Ted ever score an 8? Yes

Linq Group By Join (the Linq equivalent of SQL’s String_Agg)

If you’ve ever used SQL’s String_Agg function, then you might go looking for it’s equivalent in Linq. The String_Agg aggregation function takes a set of values and combines them into a string, using a supplied separator. Here’s an example of doing exactly that with Linq Group By:

var scores = new List<Record>()
{
    new Record() { Name = "Bill", Score = 2 },
    new Record() { Name = "Ted", Score = 9 },
    new Record() { Name = "Bill", Score = 1 },
    new Record() { Name = "Ted", Score = 8 },
    new Record() { Name = "Bill", Score = 9 },
    new Record() { Name = "Ted", Score = 5 },
};

var grouping = scores.GroupBy(x => x.Name);

foreach (var group in grouping)
{
    Console.WriteLine(
        $"{group.Key}: {string.Join(", ", group.Select(x => x.Score))}");
}

This again uses a slightly different pattern to those above, in that you don’t need a Linq aggregation function to achieve the required result. Instead we can use string.Join. This code outputs:

Bill: 2, 1, 9
Ted: 9, 8, 5

Linq Group By vs SQL Group By

I’ve touched on this before in the Dictionary Shorthand post, but while Linq Group By is very similar to SQL Group By, the main difference is that SQL Group By combines the aggregation step with the Grouping, while with Linq, the Group By and the Aggregation are separate.

In SQL this mean you’re forced to explain how you want the results to be aggregates, with Linq, you don’t have to.

With Linq you can easily write your own aggregation code (see the String_Agg section above for an example), while you’re pretty limited in this regard with SQL.

I used to prefer SQL’s approach, since it’s what I learnt first and I find it simpler. The more I use Linq Group By however, the more I appreciate the flexibility and power you get from keeping the aggregation separate, even if it does take some getting used to.

Conclusion

Linq Group By is an incredibly powerful way to analyse a group of results and to summarise data (when combined with a Linq aggregation). This type of summarising has always been a core part of SQL, and it’s inclusion in the C# language is, at least by this developer, very much appreciated!

C# Linq Count – When to use the Count property or the Count() method

C# Linq Count Example

As is now customary on this site, lets start by diving in to an example of Linq Count, showing it in action:

var numbers = new List<int>() { 1, 2, 3 };

Console.WriteLine(
    numbers.Count());

This outputs:

3

ICollection Count Example

Hang on, you might be thinking, I’m not used to seeing brackets () after Count. Isn’t count a property? And the answer is that sometimes, particularly for objects implementing ICollection, it is. For example:

var numbers = new List<int>() { 1, 2, 3 };

Console.WriteLine(
    numbers.Count);

Which also outputs:

3

But the above isn’t IEnumerable.Count (System.Linq), it’s ICollection.Count (System.Collections.Generic).

What’s the difference between IEnumerable.Count() and IColection.Count?

When you’re working with a list (or some other object that implements both ICollection and IEnumerable) you have a choice when calling count – call it without () to use the ICollection property, or call it with the () to use the IEnumerable method:

var numbers = new List<int>() { 1, 2, 3, 4, 5 };

// ICollection property
Console.WriteLine(numbers.Count);

// IEnumerable method - only works if using System.Linq
Console.WriteLine(numbers.Count());

Both return the same value, so what’s the difference?

Thanks to the wonder that is open source we can see that there really isn’t a difference. The following is taken from the .NET Core source code and shows part of the implementation of the Linq Contains method:

namespace System.Linq
{
    public static partial class Enumerable
    {
        public static int Count<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }

            if (source is ICollection<TSource> collectionoft)
            {
                return collectionoft.Count;
            }
        ...
        }
    }
}

Here we can see (on line 12-14) that where possible, the IEnumerable method will call the property on the collection.

This means that whichever you opt for, you’ll get the same performance.

Conclusion

We’ve seen that for ICollections like List, you can use either the Count property or the count() method and you won’t suffer a significant performance hit. It’s mostly a matter of style.

Personally, I default to using the property if it’s available (it makes it clearer that the call is fairly performant) but some people prefer the use of Count() as it makes certain refactoring simpler, it’s ultimately personal preference.

C# Linq Contains

A Linq Contains Example

There’s more to the Contains method than meets the eye, but we’ll get into that below. First an example of Linq Contains in action:

 var numbers = new List<int>() { 1, 2, 3, 4, 5 };

Console.WriteLine(
    numbers.Where(x => x > 4)
    .Contains(3)
    ? "Yes it does!"
    : "No, it doesn't");

Which outputs:

No, it doesn't

Before I get into what makes this a Linq contains, versus a run of the mill List.Contains, I’ll also provide an example of the later:

List.Contains Example

var numbers = new List<int>() { 1, 2, 3 };

Console.WriteLine(
    numbers.Contains(3)
    ? "Yes it does!"
    : "No, it doesn't");

Output:

Yes it does!

Here we’re using the System.Collections.Generic.List.Contains method. If you try it, you’ll see you don’t need to import Linq.

What’s the difference between Linq Contains and List.Contains?

The difference is that List.Contains only works with a List (it’s actually a little broader, since anything implementing ICollection provides a Contains method), while Linq Contains works with any IEnumerable.

To make this clear, you could work with the IEnumerable explicitly, like this:

static void Main()
{
    var numbers = new List<int>() { 1, 2, 3 };

    Console.WriteLine(
        ContainsThree(numbers)
        ? "Yes it does!"
        : "No, it doesn't");
}

static bool ContainsThree(IEnumerable<int> numbers)
{
    return numbers.Contains(3);
}

Which again returns:

Yes it does!

This is a contrived example, but it serves to highlight the fact that there is a contains methods in both System.Collections.Generic, and System.Linq.

Why is this useful?

But our first example shows a very common use case, chaining a Linq Contains after a Linq Where clause:

var numbers = new List<int>() { 1, 2, 3, 4, 5 };

Console.WriteLine(
    numbers.Where(x => x > 4)
    .Contains(3)
    ? "Yes it does!"
    : "No, it doesn't");

This is so useful because Linq statements (Where, Select etc) so often produce IEnumerables.

ICollection.Contains vs Linq.IEnumberable.Contains

Which performs better, and does it matter which ones I use in my code?

We could try and run some performance tests to see which one performs better for a particular set of inputs, but since large parts of C# have been open sourced, we can do better.

The following is taken from the .NET Core source code:

namespace System.Linq
{
    public static partial class Enumerable
    {
        public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value) =>
            source is ICollection<TSource> collection ? collection.Contains(value) :
            Contains(source, value, null);
    }
    ...
}

This code tells us that for anything that implements ICollection (such as a List) the collection’s version will be used. The custom Linq IEnumerable version will only be used for objects that aren’t an ICollection.

This is a good thing since it means that whenever you have a choice, both methods will perform identically. That is to say, you can relax – you don’t need to worry about it!

C# Linq Get Dictionary Where Value Not Equal

The idea here is to get the elements from a dictionary where the values do not match a given value. This is easily done with the Linq Where clause and a lambda expression:

var numbers = new Dictionary<int, string>()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
};

var results = numbers.Where(x => x.Value != "Two");

foreach (var result in results)
{
	Console.WriteLine(result);
}

This returns:

[1, One]
[3, Three]

I’ve used “Two” here as en example of the value you want to exclude, but you could easily use a variable or a passed in parameter.

Choosing what you return

Looking more closely at the variable I’ve called results, we can see it’s an IEnumerable (hover over the variable name in Visual Studio), so it could be written as:

IEnumerable<KeyValuePair<int, string>> results = numbers.Where(x => x.Value != "Two");

Assuming that’s not the type you’re after, we have a few options:

Get the list of Keys

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var keys = numbers
    .Where(x => x.Value != "Two")
    .Select(x => x.Key);

foreach (var key in keys)
{
    Console.WriteLine(key);
}

Which returns:

1
3

Get the list of Values

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var values = numbers
    .Where(x => x.Value != "Two")
    .Select(x => x.Value);

foreach (var value in values)
{
    Console.WriteLine(value);
}

Which outputs:

One
Three

Get a Dictionary

As always, there’s more than one way to achieve the required result:

Convert our IEnumerable into a Dictionary

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var results = numbers
    .Where(x => x.Value != "Two")
    .ToDictionary(x => x.Key, x => x.Value);

foreach (var item in results)
{
    Console.WriteLine($"key: {item.Key}, value: {item.Value}");
}

This outputs:

key: 1, value: One
key: 3, value: Three

The only tricky bit here is that ToDictionary() takes two lambda expressions: one to select the key and another to select the value.

This would perform well if you’re removing most of the items from the dictionary, but I suspect it’s fairly slow if it’s a large dictionary and you’re only removing a few items from it.

If that’s the case, you probably want to:

Remove the offending items from the original dictionary

var numbers = new Dictionary<int, string>()
{
    { 1, "One" },
    { 2, "Two" },
    { 3, "Three" },
};

var ItemsToRemove = numbers
    .Where(x => x.Value == "Two")
    .ToList();

foreach (var item in ItemsToRemove)
{
    numbers.Remove(item.Key);
}

foreach (var number in numbers)
{
    Console.WriteLine($"key: {number.Key}, value: {number.Value}");
}

This is likely to be faster if your dictionary is large and you’re only removing a few values. It again outputs:

key: 1, value: One
key: 3, value: Three

I appreciate I’ve done some hand waving around the performance, sorry. Let me know in the comments below if you’d like to see some benchmarks comparing these last two options.

C# Dictionary Shorthand (Initialisation syntax)

Dictionary’s in C# are great, they’re basically a hash table and give us constant lookup times. But dictionary initialisation isn’t obvious and I often have to lookup how to create new dictionaries while initialising them with values.

The following should hopefully serve as an easy reminder of the shorthand for initialising a c# dictionary.

Example 1: Dictionary shorthand for Dictionary<string, string>

var capitals = new Dictionary<string, string>()
{
    { "UK", "London" },
    { "France", "Paris" },
    { "Germany", "Berlin" }
};

Example 2: Dictionary shorthand for Dictionary<int, string>

var anniversaries = new Dictionary<int, string>()
{
    { 25, "Silver" },
    { 40, "Ruby" },
    { 50, "Gold" }
};

Example 3: Alternative Dictionary shorthand syntax (C# 6.0)

var anniversaries = new Dictionary<int, string>()
{
    [25] = "Silver",
    [40] =  "Ruby",
    [50] =  "Gold"
};

This syntax was introduced in C# 6.0 so if you find it doesn’t work for you, try updating the C# version in your project. If you use Visual Studio 2019 it should prompt you to update automatically.

Example 4: Dictionary from a List<int, string>

Another common use case is to create a dictionary from a list:

var myList = new List<KeyValuePair<int, string>>()
{
    new KeyValuePair<int, string>(25, "Silver"),
    new KeyValuePair<int, string>(40, "Ruby"),
    new KeyValuePair<int, string>(25, "Gold"),
};

var myDict = myList.ToDictionary(x => x.Key, x => x.Value);

Example 5: Dictionary from an IGrouping<string, object>

Finally the one that always trips me up, using a group by and getting the results back as a dictionary. In other words, C# GroupBy to Dictionary:

var results = new List<GameResult>()
{
    new GameResult { Name = "George", Points = 10 },
    new GameResult { Name = "George", Points = 10 },
    new GameResult { Name = "Ben", Points = 13 },
    new GameResult { Name = "Ben", Points = 17 },
};
 
Dictionary<string, int> totals = results
    .GroupBy(r => r.Name)
    .ToDictionary(g => g.Key, g => g.Sum(x => x.Points));

foreach (var total in totals)
{
    Console.WriteLine($"{total.Key} has {total.Value} points in total.");
}

Which returns:

George has 20 points in total.
Ben has 30 points in total.

Digression: GroupBy without aggregation

The reason this trips me up is because I’m used to SQL where you specify the aggregation at the front, e.g.:

Select Name, Max(Points)
from results
group by Name

But with C#’s linq, the group by gives you an IGrouping containing all the results, unaggregated. It’s then up to you to aggregate them afterwards, if so desired. Of course, you could always opt to do no aggregation:

var results = new List<GameResult>()
{
    new GameResult { Name = "George", Points = 10 },
    new GameResult { Name = "George", Points = 10 },
    new GameResult { Name = "Ben", Points = 13 },
    new GameResult { Name = "Ben", Points = 17 },
};
 
IEnumerable<IGrouping<string, GameResult>> totals =
    results.GroupBy(r => r.Name);
 
foreach (var group in totals)
{
    Console.WriteLine($"{group.Key} has points:");
    foreach (var item in group)
    {
        Console.WriteLine(item.Points);
    }
}

Which returns:

George has points:
10
10
Ben has points:
13
17

It’s not obvious to me how you’d get output like that in SQL!