简体   繁体   中英

Group by all properties of an object

I am trying to get a distinct list of object from one that different instances with identical values. I have tried to use the distinct and the group by. I got the group by working, but I don't want to rewrite the function when I update the object.

    // my object: 
    public class dummyObject
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    [TestMethod]
    public void dummytest()
    {
        // my list:
        var list = new List<dummyObject>
        {
            new dummyObject{ Id = 1, Name = "derp" },
            new dummyObject{ Id = 2, Name = "derp" },
            new dummyObject{ Id = 1, Name = "flerp" },
            new dummyObject{ Id = 1, Name = "derp" },
        };
        // this wont work, unless I override the GetHashCode and Equals function
         var result = list.Distinct(); // count = 4
        Assert.AreEqual(4, result.Count());
        // this will work if I group by all the properties that matter
        var result2 = list
       .GroupBy(x => new { x.Id, x.Name })
       .Select(x => x.First());
        Assert.AreEqual(3, result2.Count());
    }

I don't want to specify all of the properties that matter, since it's possible that more will be added, and i want to keep this low maintenance. I know that I'll always want to use all the properties.

Is there a better way of doing what I'm trying to do? Or am I stuck using Group by or overriding the GetHashCode and Equals functions?

Create a generic Comparer:

public class MyObjectComparer : IEqualityComparer<MyObject>
{
    public bool Equals(MyObject a, MyObject b)
    {
        var properties = a.GetType().GetProperties();
        foreach (var prop in properties)
        {
            var valueOfProp1 = prop.GetValue(a);
            var valueOfProp2 = prop.GetValue(b);

            if (!valueOfProp1.Equals(valueOfProp2))
            {
                return false;
            }
        }

        return true;
    }

    public int GetHashCode(MyObject item)
    {
        return item.A.GetHashCode();
    }
}

And use it:

var duplicates = myObjectList.GroupBy(t => t, new MyObject.MyObjectComparer()).Where(t => t.Count() > 1).Select(t => t.Key).ToList();

You will have to make your own Comparator and override the GetHashCode and Equals functions. There is no way around it, the function Distinct cannot on which properties to assert if you don't tell it. It is an object and not a primitive after all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM