C#: Difference between Intersect and Union

A thumbnail showing C# Intersect vs Union code.

C# Intersect vs Union

The main difference between Intersect and Union in C# is that Intersect returns element that overlap in both collections, while Union combines elements from both collections.

Both Intersect and Union are methods in System.Linq namespace. They both exclude duplicates from the return set.

Intersect produces the set intersection of two sequences by using the default equality comparer to compare values.

Union produces the set union of two sequences by using the default equality comparer.

C#
List<int> firstBucket = new() { 1, 2, 3, 4, 5 };
List<int> secondBucket = new () { 3, 4, 5, 6, 7};

var intersection = firstBucket.Intersect(secondBucket);
var union = firstBucket.Union(secondBucket);

Console.WriteLine(string.Join(",", intersection)); // 3,4,5
Console.WriteLine(string.Join(",", union)); // 1, 2, 3, 4, 5, 6, 7

How to find match between two collections?

To find matches between two collections in C#, use the Intersect method of System.Linq:

C#
List<int> firstBucket = new() { 1, 2, 3, 4, 5 };
List<int> secondBucket = new () { 3, 4, 5, 6, 7};

IEnumerable<int> intersection = firstBucket.Intersect(secondBucket);
Console.WriteLine(string.Join(",", intersection)); // 3,4,5

In the example above, note that the intersection variable is of type IEnumerable, not List. IEnumerable has deferred execution, so the code above our Intersection is only computed at the time of enumeration.

See my article on IEnumerable vs List for more details.

How to determine if two elements of a collection are equal?

.NET uses the IEqualityComparer interface to determine if two elements of a collection are equal.

To implement custom equality comparer in C#:

  1. Inherit from the abstract EqualityComparer class.
  2. Override the Equals(T, T) method with definition on how to compare two objects.
  3. Override the GetHashCode to provide unique integer hashcode.

Full example of how to implement EqualityComparer:

C#
class Person 
{
    public string Name {get; set;}
    public int SSN {get; set;}
}
class PersonComparer : EqualityComparer<Person>
{
    public override bool Equals(Person p1, Person p2)
    {
        if (p1 == null && p2 == null)
            return true;
        else if (p1 == null || p2 == null)
            return false;

        return (p1.SSN == p2.SSN);
    }

    public override int GetHashCode(Person p)
    {
        return p.SSN.GetHashCode();
    }
}

Intersect implementation

In .NET, the Intersect method is based on internal class Set, foreach loop, and IEqualityComparer interface:

C#
 static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
    Set<TSource> set = new Set<TSource>(comparer);
    foreach (TSource element in second) set.Add(element);
    foreach (TSource element in first)
        if (set.Remove(element)) yield return element;
}

See the full source code on GitHub.

Union implementation

In .NET, the Union method is based on internal class Set, foreach loop, and IEqualityComparer interface:

C#
static IEnumerable<TSource> UnionIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
    Set<TSource> set = new Set<TSource>(comparer);
    foreach (TSource element in first)
        if (set.Add(element)) yield return element;
    foreach (TSource element in second)
        if (set.Add(element)) yield return element;
}

Conclusion

  • Intersect yields the elements that two sequences have in common.
  • Union combines all the elements of the first and second sequence, but removes any duplicates.
Free Software Developer Career Guide

In just 7 actionable steps you can sharpen your career.

I've used these principles to increase my earnings by 63% in two years. So can you.

Published on