Reputation: 773
I need to compare two lists, that contains objects of the same class, however not every property should be used to check for difference. Eg. the Id (primary key) property should not be used.
My example class:
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" });
What I would like to do with the above, is to match the two lists on the VMId property. Next I would like to check if the Name property has changed from oldR to newR.
Basically I would like to now, that Test1 should be removed from database, Test6 should be added, and Test4 should gets updated to Test43.
Hope it makes sence
EDIT: I should mention that my real class has +20 properties. I would like to now how to use linq to compare, without specifying them all? And maybe just exclude the Id property that I don't want to compare
How can I accomplish that?
Upvotes: 1
Views: 141
Reputation: 8655
There are a few standard ways to do this type of thing in C#.
If you have control over the class being compared, you can make it implement the IEquatable<T>
interface and overload the Object.Equals
method to define how instances are compared. You should also override Object.GetHashCode
to make sure equality in Dictionary
s and other hash collections works properly.
Example:
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();
}
If you don't have control over that class, you can create a class that implements the IEqualityComparer<T>
interface, which can compare instances of another class.
Example:
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();
}
Many of the standard LINQ operators have overloads accepting IEqualityComparers
as extra parameters for element comparison.
Upvotes: 3
Reputation: 324
Please look into this thread implement equatable
this will be important because it will allow you to do oldR[i].Equals(newR). Just use a nested foreach that checks all the objects and spits out a list of which items should be removed and which should be added (you could do this with removeList and addList). if you go the linq route, having the iequatable should be useful and the linq query should be simpler to write.
Upvotes: 2