我需要比较两个包含同一类对象的列表,但不是每个属性都应该用于检查差异。例如。不应使用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属性
我该如何实现?
答案 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查询应该更容易编写。