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!