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!