C#在两个匹配列表中获得差异

时间:2016-12-07 03:48:17

标签: c# linq

我需要比较两个包含同一类对象的列表,但不是每个属性都应该用于检查差异。例如。不应使用Id(主键)属性。

我的示例课程:

class MyClass
{
    public System.Nullable<int> Id { get; set; }
    public int VMId { get; set; }
    public string Name { get; set; }
}

var oldR = new List<MyClass>();
oldR.Add(new MyClass() { Id = 1, VMId = 11, Name = "Test1" });
oldR.Add(new MyClass() { Id = 2, VMId = 22, Name = "Test2" });
oldR.Add(new MyClass() { Id = 3, VMId = 33, Name = "Test3" });
oldR.Add(new MyClass() { Id = 4, VMId = 44, Name = "Test4" });
oldR.Add(new MyClass() { Id = 5, VMId = 55, Name = "Test5" });

var newR = new List<MyClass>();
newR.Add(new MyClass() { Id = null, VMId = 22, Name = "Test2" });
newR.Add(new MyClass() { Id = null, VMId = 33, Name = "Test3" });
newR.Add(new MyClass() { Id = null, VMId = 44, Name = "Test43" });
newR.Add(new MyClass() { Id = null, VMId = 55, Name = "Test5" });
newR.Add(new MyClass() { Id = null, VMId = 66, Name = "Test6" });

我想用上面的内容来匹配VMId属性上的两个列表。接下来,我想检查Name属性是否已从oldR更改为newR。

基本上我想现在,应该从数据库中删除Test1,应该添加Test6,并且Test4应该更新到Test43。

希望它能成为现实

编辑: 我应该提到我的真正的班级有+20属性。我现在想如何使用linq进行比较,而不是全部指定它们?也许只是排除我不想比较的Id属性

我该如何实现?

2 个答案:

答案 0 :(得分:3)

在C#中有几种标准方法可以做这种事情。

如果您可以控制所比较的类,则可以使其实现IEquatable<T>接口并重载Object.Equals方法以定义实例的比较方式。您还应该重写Object.GetHashCode以确保Dictionary和其他哈希集合中的相等性能正常工作。

示例:

class MyClass : IEquatable<MyClass> {

    public string name;
    public int primaryKey;

    //IEquatable<T> implementation
    public bool Equals(MyClass other) => 
        !Equals(other, null) 
        && other.name == this.name;

    //Overriding Object methods
    public override bool Equals(object other) =>
        Equals(other as MyClass);

    public override int GetHashCode() => name.GetHashCode();
}

如果您无法控制该类,则可以创建一个实现IEqualityComparer<T>接口的类,该类可以比较另一个类的实例。

示例:

class MyComparer : IEqualityComaprer<MyClass> {
    public bool Equals(MyClass a, MyClass b) {
        if (Object.Equals(a, null)) return Object.Equals(b, null);
        if (Object.Equals(b, null)) return false;
        return a.name == b.name;
    }

    public int GetHashCode(MyClass obj) => obj.name.GetHashCode();
}

许多标准LINQ运算符都有重载接受IEqualityComparers作为元素比较的额外参数。

答案 1 :(得分:2)

请查看此主题implement equatable

这很重要,因为它可以让你做oldR [i] .Equals(newR)。只需使用一个嵌套的foreach来检查所有对象并吐出一个列表,列出哪些项应该被删除以及应该添加哪些项(你可以用removeList和addList来做)。如果你去linq路由,那么iequatable应该是有用的,而linq查询应该更容易编写。