TheDeveloperBlog.com


C# Contains Extension Method

Contains returns true or false. It indicates whether the IEnumerable collection has an element matching the argument. It acts upon any IEnumerable collection when the System.Linq namespace is included.

Note: Contains is an extension method, and can be called on arrays, Lists and certain other collections.

Extension Method

Note 2: Some collections, such as List, contain their own Contains method—this is an instance method. Performance is better.


Example. To start, this program tests the Contains extension method, and the List method, on the same List. The result is the same for both Contains calls. The element with value 7 is located within the List.

C# program that uses Contains

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
	var list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	// Use extension method.
	bool a = list.Contains<int>(7);
	// Use instance method.
	bool b = list.Contains(7);

	Console.WriteLine(a);
	Console.WriteLine(b);
    }
}

Output

True
True

In this example, the first Contains call specifies the type parameter int in the angle brackets. This tells the C# compiler to select the extension method version of Contains, not the List type's version.

Generic Method

Performance. The different Contains methods are implemented with different code. The version specific to List, found on the List type definition, is faster. I tested the same List with the two Contains methods.

Note: In this benchmark, the Contains methods both return true as in the above program.

Benchmark

Note 2: The exception code is used to ensure the C# compiler does not optimize out the Contains calls.

Result: The Contains method (on List) is faster than the Contains extension. It thus should be preferred.

List used in benchmark: C#

var list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

Inner loop tested 1: C#

bool a = list.Contains<int>(7);
if (!a)
{
    throw new Exception();
}

Inner loop tested 2: C#

bool b = list.Contains(7);
if (!b)
{
    throw new Exception();
}

Results

46.50 ns    Extension method
39.99 ns    List method


Discussion. Internally, the Contains extension method checks for errors. It then uses the IEnumerable type's enumerator implementation to loop through the elements. In a List, this searches forward. The MoveNext method is used.

So: The performance disparity here is mainly due to more low-level code in List Contains.

And: List Contains internally does not use enumerators or MoveNext—it uses a loop construct and checks elements. This is lower-level.

List Contains

Summary. The Contains extension method can be called on any type that implements IEnumerable, even ones you implement yourself. It has no relation to the List Contains method, except the name and concept.