1

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?

4
  • Try linq queries. That may help you to compare the objects easily Commented Dec 7, 2016 at 3:52
  • 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 Commented Dec 7, 2016 at 3:53
  • I would use a left outer join to combine lists VMID. See msdn : code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b Commented Dec 7, 2016 at 4:12
  • stackoverflow.com/questions/2502395/… try this Commented Dec 7, 2016 at 11:32

2 Answers 2

3

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 Dictionarys 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.

Sign up to request clarification or add additional context in comments.

2 Comments

Please prefer IEqualityComparer<> always and provide the desired comparer to the function where you need it. By overriding Equals() and GetHashCode() you change the default behavior and this can lead to unexpected behavior when you use the class in a different context.
@Oliver makes a good point. IEquatable is to define the default comparison on that type. Do not use it to meet the needs of just one specific usage of that class. IEqualityComparer is much better for situations that need a specific non-standard comparison.
2

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.