LINQ / C#

LINQ Except Operator

LINQ Except operator comes under Set operators category in LINQ. LINQ Set operators is used for compare two sequences (collections) and find common, missing and unique elements. You can find entire list of set operators here.

Except operator compares two sequences (collections) classes and find those elements which are not present in second sequence. For example. suppose we have a collection A = { 1, 2, 3 } and B = { 1, 3 }. R = A EXCEPT B = { 2 }. 2 element is only available in first collection A and not available in second collection B.

Except operator is an extension method which takes a single parameter of second sequence. Below is the syntax:


public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second);

public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer);

Except operator is only available in Method Syntax and not available in Query Syntax.

C# LINQ Except Example of Two Lists

string[] delhiResidents = { "Ramesh", "Kapil", "Vikas", "Amit" };
string[] kolkataResidents = { "Kapil", "Manmohan", "Deepak", "Amit" };

var onlyDelhiResidents = delhiResidents.Except(kolkataResidents);

Console.WriteLine("Only Delhi Residents:");
foreach (var item in onlyDelhiResidents)
{
    Console.WriteLine(item);
}

Result
------
Only Delhi Residents:
Ramesh
Vikas

LINQ Except Example of IEqualityComparer

By default, exception operator does not work with Custom Types. It compares objects basis on string return by ToString() method. To compare custom types we need to use second overload method of Except method which takes an IEqualityComparer interface as parameter.

IEqualityComparer has two methods Equals and GetHasCode. We need to create a new class which implement this IEqualityComparer interface. Below is the example.

internal class Resident
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}

internal class ResidentNameComparer : IEqualityComparer<Resident>
{
    public bool Equals(Resident x, Resident y)
    {
        if (string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase))
        {
            return true;
        }
        return false;
    }

    public int GetHashCode(Resident obj)
    {
        return obj.Name.GetHashCode();
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        List<Resident> delhiResidents = new List<Resident>();
        delhiResidents.Add(new Resident { Id = 1, Name = "Ramesh", City = "Delhi" });
        delhiResidents.Add(new Resident { Id = 2, Name = "Kapil", City = "Delhi" });
        delhiResidents.Add(new Resident { Id = 3, Name = "Vikas", City = "Delhi" });
        delhiResidents.Add(new Resident { Id = 4, Name = "Amit", City = "Delhi" });

        List<Resident> kolkataResidents = new List<Resident>();
        kolkataResidents.Add(new Resident { Id = 5, Name = "Kapil", City = "Kolkata" });
        kolkataResidents.Add(new Resident { Id = 6, Name = "Manmohan", City = "Kolkata" });
        kolkataResidents.Add(new Resident { Id = 7, Name = "Deepak", City = "Kolkata" });
        kolkataResidents.Add(new Resident { Id = 8, Name = "Amit", City = "Kolkata" });

        var onlyDelhiResidents = delhiResidents.Except(kolkataResidents, new ResidentNameComparer());

        Console.WriteLine("Only Delhi Residents:");
        foreach (var item in onlyDelhiResidents)
        {
            Console.WriteLine(item.Name);
        }
    }
}

Result
------
Only Delhi Residents:
Ramesh
Vikas

We have created a new class ResidentNameCompare which implement the IEqualityComparer interface. We implement both methods Equals and GetHashCode. We need to implement both methods both are required to compare. In the Equals method implementation, we compare Name property of two Residents objects using string.equals methods and in GetHashCode we return hash code of Name property of Resident object.