Comparing Collections Using Except and Intersect in C#

We have two extension methods in c# to match unique elements and find unmatched elements between two collections, Except and Intersect.

We are talking here two lists of user models and will check with email and mobile number elements

List<User> collection1 = new() { 
    new User { Id=1, FirstName="first1", LastName="last1", MobileNumber="9876543210", Email="[email protected]" },
    new User { Id=2, FirstName="first2", LastName="last2", MobileNumber="7776543210", Email="[email protected]" },
    new User { Id=3, FirstName="first3", LastName="last3", MobileNumber="8888765432", Email="[email protected]" }
};

List<User> collection2 = new() { 
    new User { Id=4, FirstName="first1coll2", LastName="last1coll2", MobileNumber="9876543210", Email="[email protected]" },
    new User { Id=5, FirstName="first2coll2", LastName="last2coll2", MobileNumber="7776543210", Email="[email protected]" },
    new User { Id=6, FirstName="first3coll2", LastName="last3coll2", MobileNumber="9998765432", Email="[email protected]" }
};

1. Except

It returns unmatched items from the first collection
Suppose we have two lists of items, and we want to find out items that are available in one but not available in the second list. Then we can use Except, which will return a new collection of lists with mo matched items.
Except will always return the first collection's items that are not available in the second collection.

Code Snippet

Console.WriteLine("------Except-------");

// We can use whole collection if want to compare each elements like: collection1.Except(collection2).ToList();.
// Here we will check for unmtached items based on some selected elements.
// It will return collection1's items that are not available in collection2
var nonMatchedElements = collection1.Select(s => new { s.MobileNumber, s.Email }).Except(collection2.Select(s => new { s.MobileNumber, s.Email })).ToList();
Console.WriteLine("Non-Matched Elements: " + JsonSerializer.Serialize(nonMatchedElements));

List<User> nonMatchedCollection = collection1.Where(x => nonMatchedElements.Any(a => a.Email == x.Email) && nonMatchedElements.Any(a => a.MobileNumber == x.MobileNumber)).ToList();
Console.WriteLine("Non-Matched Collection: " + JsonSerializer.Serialize(nonMatchedCollection));

Output

Except

2. Intersect

It returns only matched items from the first collection
Now, suppose we want to find items that are available in one as well as in the second list, and then we can use the Intersect extension method.
Same as Except, It will also return the first collection's items matched with the second collection.

Code Snippet

Console.WriteLine("\n------Intersect-------");

// We can use whole collection if want to compare each elements like: collection1.Intersect(collection2).ToList();.
// Here we will check for mtached items based on some selected elements.
// It will return collection1's items that are available in collection2
var matchedElements = collection1.Select(s => new { s.MobileNumber, s.Email }).Intersect(collection2.Select(s => new { s.MobileNumber, s.Email })).ToList();
Console.WriteLine("Matched Elements: " + JsonSerializer.Serialize(matchedElements));
    
List<User> matchedCollection = collection1.Where(x => matchedElements.Any(a => a.Email == x.Email) && matchedElements.Any(a => a.MobileNumber == x.MobileNumber)).ToList();
Console.WriteLine("Matched Collection: " + JsonSerializer.Serialize(matchedCollection));

Output

Intersect

Conclusion

Here, when we use the Except method and compare two elements, email and mobile number, then it returns non-matched items from collection1, and when we use Intersect, then it returns matched items based on these two elements.

So if want to compare two list or array with some elements and find outmatched and unmatched items as new result collection then these two methods are usefull.