HOWTO · Csharp

How to Compare Two Lists in C#

Compare two C# lists in both directions with LINQ Except() or filtering with List.Contains(), and choose based on duplicate behavior and list size.

On this page

To compare two lists for differences in C#, find the elements present in list1 but not list2, then repeat the operation in the opposite direction. One approach returns distinct results; filtering with a membership check keeps repeated unmatched occurrences from the source list. Choose between them according to whether duplicates matter and how large the lists are.

Run this complete example to find values in list1 that are not in list2:

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

class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 1, 2, 3, 4 };
        List<int> list2 = new List<int> { 3, 4, 5, 6 };
        List<int> firstNotSecond = list1
            .Where(item => !list2.Contains(item))
            .ToList();

        foreach (int item in firstNotSecond)
        {
            Console.WriteLine(item);
        }
    }
}
1
1
2

Compare Two Lists for Differences With LINQ Except

The Except() method is in LINQ, or Language Integrated Query. It returns the distinct elements from its first sequence that do not occur in its second sequence. Call it once for each direction to get both sets of differences. The lists below are the same ones used in the other examples, and list1 contains the unmatched value 1 twice.

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

class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 1, 2, 3, 4 };
        List<int> list2 = new List<int> { 3, 4, 5, 6 };
        List<int> firstNotSecond = list1.Except(list2).ToList();
        List<int> secondNotFirst = list2.Except(list1).ToList();

        Console.WriteLine("Present in list1 but not in list2");
        foreach (int item in firstNotSecond)
            Console.WriteLine(item);

        Console.WriteLine("Present in list2 but not in list1");
        foreach (int item in secondNotFirst)
            Console.WriteLine(item);
    }
}

Because Except() produces distinct elements, the first result contains 1 once, followed by 2; the second contains 5 and 6. The duplicate in the input does not create another copy in the result. This behavior is useful when the question is which values are missing from the other list, regardless of how many times a value occurs in the source.

Compare Two Lists While Preserving Duplicates With List.Contains

List.Contains(item) reports whether a value occurs in a list. Use it in a LINQ Where filter to retain each source item for which the other list has no match. Apply the filter in both directions, as in this complete program:

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

class Program
{
    static void Main()
    {
        List<int> list1 = new List<int> { 1, 1, 2, 3, 4 };
        List<int> list2 = new List<int> { 3, 4, 5, 6 };
        List<int> firstNotSecond = list1
            .Where(item => !list2.Contains(item))
            .ToList();
        List<int> secondNotFirst = list2
            .Where(item => !list1.Contains(item))
            .ToList();

        Console.WriteLine("Present in list1 but not in list2");
        foreach (int item in firstNotSecond)
            Console.WriteLine(item);

        Console.WriteLine("Present in list2 but not in list1");
        foreach (int item in secondNotFirst)
            Console.WriteLine(item);
    }
}

Filtering preserves the source list’s traversal order and every unmatched occurrence. With these values, the first direction therefore retains two occurrences of 1 and one of 2; the reverse direction retains 5 and 6. If the original position and multiplicity of unmatched items matter, this is the behavior to use. The Contains() check tests membership; it does not consume a matching item or pair duplicates one at a time.

Choose a Method Based on Duplicate Semantics and List Size

Use LINQ Except() when you need distinct values that occur in one list but not the other. Use Where with Contains() when the result should retain repeated occurrences and their source order. Both operations are directional, so compute both directions if you want a complete comparison.

For small lists, filtering with Contains() is a straightforward way to express the comparison. Each source element triggers a membership scan of the other List<T>, so doing this in both directions can require many repeated comparisons as the lists grow. This is a practical cost consideration, not a measured benchmark. Except() is purpose-built for set-style differences and avoids the repeated List.Contains() scans, but its distinct-result semantics may not suit a task that needs repeated occurrences. Decide first whether multiplicity matters, then consider list size and the cost of repeated scans.