Removing Duplicates in Lists Using LINQ: Methods and Implementation

Nov 20, 2025 · Programming · 11 views · 7.8

Keywords: LINQ | C# | Deduplication | Custom Comparer | Distinct Method

Abstract: This article provides an in-depth exploration of various methods for removing duplicate items from lists in C# using LINQ technology. It focuses on the Distinct method with custom equality comparers, which enables precise deduplication based on multiple object properties. Through comprehensive code examples, the article demonstrates how to implement the IEqualityComparer interface and analyzes alternative approaches using GroupBy. Additionally, it extends LINQ application techniques to real-world scenarios involving DataTable deduplication, offering developers complete solutions.

Overview of LINQ Deduplication Techniques

In C# programming, handling collections containing duplicate objects is a common requirement. LINQ (Language Integrated Query) provides powerful query capabilities that can efficiently address such problems. This article delves into several core methods for removing duplicates from lists using LINQ.

Basic Deduplication Method: The Distinct Operator

The Distinct method in LINQ is the most straightforward approach for deduplication, but its default behavior relies on reference equality for objects. For value types or scenarios requiring deduplication based on specific properties, custom equality comparison logic is necessary.

Implementing Custom Equality Comparers

By implementing the IEqualityComparer<T> interface, you can precisely control the criteria for deduplication. Below is a complete example of a custom comparer:

public class DistinctItemComparer : IEqualityComparer<Item>
{
    public bool Equals(Item x, Item y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x is null || y is null) return false;
        
        return x.Id == y.Id &&
               x.Name == y.Name &&
               x.Code == y.Code &&
               x.Price == y.Price;
    }

    public int GetHashCode(Item obj)
    {
        if (obj is null) return 0;
        
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + obj.Id.GetHashCode();
            hash = hash * 23 + (obj.Name?.GetHashCode() ?? 0);
            hash = hash * 23 + (obj.Code?.GetHashCode() ?? 0);
            hash = hash * 23 + obj.Price.GetHashCode();
            return hash;
        }
    }
}

In the GetHashCode method, we employ a classic hash computation pattern using prime number multiplication to minimize hash collisions. This implementation ensures that when two objects are equal, their hash codes will necessarily be identical.

Applying Custom Comparers for Deduplication

Once the comparer is implemented, it can be used with the Distinct method:

var distinctItems = items.Distinct(new DistinctItemComparer());

This approach retains the first occurrence of duplicate items in the list, removing subsequent duplicates. The resulting collection maintains the original order, which is crucial in certain business contexts.

Alternative Approach: The GroupBy Method

Besides the Distinct method, the GroupBy operator can also be used for deduplication:

var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());

This method groups elements by a specified key (such as Id) and then selects the first element from each group. While concise, it only supports deduplication based on a single property and lacks flexibility for scenarios requiring multi-property comparisons.

Extended Applications: DataTable Deduplication Scenarios

Drawing from practical development experience, LINQ deduplication techniques are equally applicable to DataTable operations. When deduplication based on multiple columns is needed, anonymous types can define composite keys:

var distinctTable = dataTable.AsEnumerable()
    .GroupBy(row => new
    {
        EmployeeID = row.Field<string>("Employee ID"),
        ProjectID = row.Field<string>("ProjectID")
    })
    .Select(group => group.First())
    .CopyToDataTable();

This pattern is particularly suitable for deduplication needs when processing database query results or imported data.

Performance Considerations and Best Practices

When selecting a deduplication method, performance factors should be considered:

Error Handling and Edge Cases

In practical applications, various edge cases need to be handled:

public bool Equals(Item x, Item y)
{
    // Handle null references
    if (x == null && y == null) return true;
    if (x == null || y == null) return false;
    
    // Handle null values for string properties
    return x.Id == y.Id &&
           string.Equals(x.Name, y.Name) &&
           string.Equals(x.Code, y.Code) &&
           x.Price == y.Price;
}

Conclusion

Implementing list deduplication through LINQ offers flexible and powerful solutions. The custom equality comparer method allows precise control over deduplication logic, making it suitable for complex business scenarios. Developers should choose the appropriate method based on specific requirements and pay attention to handling various edge cases to ensure code robustness.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.