C#仅根据某些属性查找两个自定义对象列表的差异

时间:2017-06-14 21:03:53

标签: c# list linq collections

所以我有以下对象:

public class user
{
    // navigation properties
    public DateTime lastRefresh { get; set; }
    public userParent parent { get; set; }

    // query data
    public string id { get; set; }
    public DateTime created_at { get; set; }
    public int plan { get; set; }
}

所以我正在处理这些对象的两个列表,并希望得到第三个列表,这两个集合的区别如下:

List<user> freshUsers;
List<user> oldUsers;

//code populate lists

//get difference
List<user> uniqueUsers = freshUsers.Except(oldUsers).ToList();

然而,freshUsers中的用户没有稍后手动添加的导航属性(lastRefresh和parent),即使他们这样做,lastRefresh也不会与oldUsers中的其他用户匹配。

所以我需要的是一种只根据数据属性(id,created_at,plan)获取列表之间差异的方法,并且想知道最好的方法。我应该创建一个自定义相等来做,或者是否有一些聪明的方法使用LINQ来比较适当的3个值?

2 个答案:

答案 0 :(得分:0)

在您的用户类中,实现接口IEquatable<user>。这创建了一种将一个用户对象与另一个用户对象进行比在此方法中,您需要定义两个对象何时相同(通过比较属性)。

或者......创建另一个具有比较两个用户的任务的类。您需要实施IEqualityComparer<user>。实现此接口将提供一种比较两个用户对象的方法。现在,您可以使用此比较器的实例作为第二个参数调用Except

答案 1 :(得分:0)

可能最简单的事情是覆盖Equals方法(以及GetHashCode)。然后,您可以使用System.Linq扩展方法获得所需内容:

public class user
{
    // navigation properties
    public DateTime lastRefresh { get; set; }
    public userParent parent { get; set; }

    // query data
    public string id { get; set; }
    public DateTime created_at { get; set; }
    public int plan { get; set; }

    public override bool Equals(object obj)
    {
        var other = obj as user;
        return Equals(other);
    }

    protected bool Equals(user other)
    {
        if (other == null) return false;
        return string.Equals(id, other.id) && 
            created_at.Equals(other.created_at) && 
            plan == other.plan;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = id?.GetHashCode() ?? 0;
            hashCode = (hashCode * 397) ^ created_at.GetHashCode();
            hashCode = (hashCode * 397) ^ plan;
            return hashCode;
        }
    }
}

现在,您可以使用Linq代码获得所需内容,并使用Equals覆盖代码对项目进行比较:

//get difference
List<user> uniqueUsers = freshUsers.Except(oldUsers).ToList();