GroupBy on complex object (e.g. List)

后端 未结 3 1569
自闭症患者
自闭症患者 2020-11-27 22:42

Using GroupBy() and Count() > 1 I\'m trying to find duplicate instances of my class in a list.

The class looks like this:



        
3条回答
  •  醉梦人生
    2020-11-27 23:10

    List has no overridden Equals + GetHashCode, that's why your GroupBy doesn't work as expected. One of the two properties of the anonymous type refer to the list, when the GroupBy has to compare two lists Object.RefernceEquals is used which only checks if both are the same reference and not if both contain the sample elements.

    You could provide a custom IEqualityComparer:

    public class IdEventComparer : IEqualityComparer
    {
        public bool Equals(SampleObject x, SampleObject y)
        {
            if (object.ReferenceEquals(x, y)) 
                return true;
            if (x == null || y == null) 
                return false;
            if(x.Id != y.Id) 
                return false;
            if (x.Events == null && y.Events == null)
                return true;
            if (x.Events == null || y.Events == null)
                return false;
    
            return x.Events.SequenceEqual(y.Events);
        }
    
        public int GetHashCode(SampleObject obj)
        {
            if(obj == null) return 23;
            unchecked
            {
                int hash = 23;
                hash = (hash * 31) + obj.Id == null ? 31 : obj.Id.GetHashCode();
    
                if (obj.Events == null) return hash;
                foreach (string item in obj.Events)
                {
                    hash = (hash * 31) + (item == null ? 0 : item.GetHashCode());
                }
                return hash;
            }
        }
    }
    

    Then you can use it in many LINQ methods like also GroupBy:

    var duplicates = items.GroupBy(x => x, new IdEventComparer())
         .Where(g => g.Count() > 1)
         .Select(g => g.Key)
         .ToList();
    

提交回复
热议问题