LINQ Except

Summary: in this tutorial, you will learn how to use the LINQ Except() method to retrieve the elements from one sequence that are not present in another sequence.

Introduction to the LINQ Except() method

The LINQ Except() method allows you to get the elements from the first sequence that are not in the second sequence. It returns a new sequence with the type IEnumerable<T> that contains these elements.

Here’s the syntax of the LINQ Except() method:

IEnumerable<TSource> Except<TSource> (
   this IEnumerable<TSource> first, 
   IEnumerable<TSource> second
);Code language: C# (cs)

The Except() method accepts two parameters first and second that have the IEnumerable<T> type.

The Except() method returns elements in first that don’t appear in the second but not vice versa. In other words, it doesn’t return elements in second, but don’t appear in first. Also, it returns only unique elements.

By default, the Except() method compares the elements in the sequences by their references if they are objects, or by their value if they are primitive types.

To override the default equality comparer, you implement a custom IEqualityComparer<T> and pass it to the Except() method:

IEnumerable<TSource> Except<TSource> (
   IEnumerable<TSource> first, 
   IEnumerable<TSource> second, 
   IEqualityComparer<TSource>? comparer
);Code language: C# (cs)

In this syntax, you define a class that implements the IEqualityComparer interface and pass it to the Except() method.

LINQ Except() method examples

Let’s take some examples of using the LINQ Except() method.

1) Using LINQ Except() method with a list of integers

The following example uses the Except() method to return the numbers from the first list that are not present in the second list:

using static System.Console;


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

var numbers = numbers1.Except(numbers2);

foreach (var number in numbers)
{
    WriteLine(number);
}Code language: C# (cs)

Output:

3
4Code language: C# (cs)

2) Using LINQ Except() method with a list of strings

The following example uses the Except() method to return elements of the first list but are not in the second list:

using static System.Console;


var fruits1 = new List<string>() 
{ 
    "Apple", 
    "Orange", 
    "Banana", 
    "Strawberry" 
};

var fruits2 = new List<string>() 
{ 
    "Banana", 
    "Strawberry" 
};

var fruits = fruits1.Except(fruits2);
foreach (var fruit in fruits)
{
    WriteLine(fruit);
}Code language: C# (cs)

Output:

Apple
OrangeCode language: C# (cs)

3) Using LINQ Except() method with a list of objects

Suppose you have a Person class with properties SSN and Name:

public class Person
{
    public required string SSN
    {
        get; set;
    }
    public required string Name
    {
        get; set;
    }

    public override string ToString() => $"{Name}<{SSN}>";
}Code language: C# (cs)

The following example uses the Except() method to find the potential candidates who are in the candidate list but not in the Employees list:

using static System.Console;

var candiates = new List<Person>
{
    new Person() { SSN="111222333", Name="John Doe" },
    new Person() { SSN="111222334", Name="Jane Doe" },
    new Person() { SSN="111222335", Name="Emily Johnson" },
    new Person() { SSN="111222336", Name="William Brown" },
    new Person() { SSN="111222337", Name="Sarah Davis" },
};

var employees = new List<Person>
{
    new Person() { SSN="111222333", Name="John Doe" },
    new Person() { SSN="111222334", Name="Jane Doe" }
};


var potentialCandidates = candiates.Except(employees);

foreach (var candidate in potentialCandidates)
{
    Console.WriteLine(candidate);
}Code language: C# (cs)

Output:

John Doe <111222333>
Jane Doe <111222334>
Emily Johnson <111222335>
William Brown <111222336>
Sarah Davis <111222337>Code language: C# (cs)

It returns all the elements in the candidate’s list. The reason is that the Except() method compares the object by references by default.

Even though the two objects have the same properties, they are not referencing the same object. Therefore, they are not considered equal.

Suppose that two people are the same if they have the same SSN, you can implement a customer IEqualityComparer:

public class PersonComparer : IEqualityComparer<Person>
{
    public bool Equals(Person? x, Person? y)
    {
        // Check for null values
        if (x == null || y == null)
            return false;

        // Check if the two Person objects are the same reference
        if (ReferenceEquals(x, y))
            return true;

        // Compare the SSN of the two Person objects
        // to determine if they're the same
        return x.SSN == y.SSN;
    }

    public int GetHashCode(Person? obj)
    {
        if (obj == null || obj.SSN == null)
            return 0;

        // Use the SSN of the Person object
        // as the hash code
        return obj.SSN.GetHashCode();
    }
}Code language: C# (cs)

And pass the PersonComparer to the Except() method:

using static System.Console;

var candiates = new List<Person>
{
    new Person() { SSN="111222333", Name="John Doe" },
    new Person() { SSN="111222334", Name="Jane Doe" },
    new Person() { SSN="111222335", Name="Emily Johnson" },
    new Person() { SSN="111222336", Name="William Brown" },
    new Person() { SSN="111222337", Name="Sarah Davis" },
};

var employees = new List<Person>
{
    new Person() { SSN="111222333", Name="John Doe" },
    new Person() { SSN="111222334", Name="Jane Doe" }
};


var potentialCandidates = candiates.Except(
    employees,
    new PersonComparer()
);

foreach (var candidate in potentialCandidates)
{
    Console.WriteLine(candidate);
}Code language: C# (cs)

Output:

Emily Johnson <111222335>
William Brown <111222336>
Sarah Davis <111222337>Code language: C# (cs)

Summary

  • Use the LINQ Except() method to retrieve elements from the first list that are not in the second list.
  • Use a custom IEqualityComparer to override the default equality comparer.
Was this tutorial helpful ?