按对象的所有属性分组

时间:2017-10-18 16:40:30

标签: c# linq

我试图从具有相同值的不同实例的对象中获取一个不同的对象列表。我试图使用distinct和group by。我通过工作得到了这个小组,但是当我更新对象时,我不想重写该功能。

    // 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());
    }

我不想指定所有重要的属性,因为可能会添加更多属性,并且我希望保持这种低维护。我知道我总是想要使用所有属性。

有没有更好的方法来做我想做的事情?或者我是否坚持使用分组或覆盖GetHashCodeEquals函数?

2 个答案:

答案 0 :(得分:2)

创建通用比较器:

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();
    }
}

并使用它:

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

答案 1 :(得分:1)

您必须创建自己的Comparator并覆盖GetHashCode和Equals函数。没有办法绕过它,如果你不告诉它,功能Distinct不能断言要断言的属性。它毕竟是一个对象,而不是原始的