LINQ's Distinct() on a particular property

后端 未结 20 2088
一向
一向 2020-11-21 05:05

I am playing with LINQ to learn about it, but I can\'t figure out how to use Distinct when I do not have a simple list (a simple list of integers is pretty easy

20条回答
  •  再見小時候
    2020-11-21 05:45

    If you don't want to add the MoreLinq library to your project just to get the DistinctBy functionality then you can get the same end result using the overload of Linq's Distinct method that takes in an IEqualityComparer argument.

    You begin by creating a generic custom equality comparer class that uses lambda syntax to perform custom comparison of two instances of a generic class:

    public class CustomEqualityComparer : IEqualityComparer
    {
        Func _comparison;
        Func _hashCodeFactory;
    
        public CustomEqualityComparer(Func comparison, Func hashCodeFactory)
        {
            _comparison = comparison;
            _hashCodeFactory = hashCodeFactory;
        }
    
        public bool Equals(T x, T y)
        {
            return _comparison(x, y);
        }
    
        public int GetHashCode(T obj)
        {
            return _hashCodeFactory(obj);
        }
    }
    

    Then in your main code you use it like so:

    Func areEqual = (p1, p2) => int.Equals(p1.Id, p2.Id);
    
    Func getHashCode = (p) => p.Id.GetHashCode();
    
    var query = people.Distinct(new CustomEqualityComparer(areEqual, getHashCode));
    

    Voila! :)

    The above assumes the following:

    • Property Person.Id is of type int
    • The people collection does not contain any null elements

    If the collection could contain nulls then simply rewrite the lambdas to check for null, e.g.:

    Func areEqual = (p1, p2) => 
    {
        return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
    };
    

    EDIT

    This approach is similar to the one in Vladimir Nesterovsky's answer but simpler.

    It is also similar to the one in Joel's answer but allows for complex comparison logic involving multiple properties.

    However, if your objects can only ever differ by Id then another user gave the correct answer that all you need to do is override the default implementations of GetHashCode() and Equals() in your Person class and then just use the out-of-the-box Distinct() method of Linq to filter out any duplicates.

提交回复
热议问题