Reputation: 2197
i need to compare two objects but compare a number of their properties in one hit. this is not for sorting, but instead to confirm whether anything has changed; as one is the old saved instance, and the second is a newly imported instance of the same thing
i assume this is best served by writing a custom comparer. just am a bit confused as to whether to do IComparer
, or IComparable
, or what tbh.
thanks
nat
Upvotes: 10
Views: 5767
Reputation: 113472
If you only have a single definition of equality for your class, you don't really need to implement any interface: simply override the Equals
method. Best practice though, would be to implement IEquatable<T>
and to override GetHashCode
sensibly (if you don't override the hash-code, equality will misbehave when collection classes, LINQ methods etc. use it as a pre-condition for equality). Here's a sample implementation:
public class Person : IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public override int GetHashCode()
{
return (Name == null ? 0 : Name.GetHashCode()) ^ Age;
}
public override bool Equals(object obj)
{
return Equals(obj as Person);
}
public bool Equals(Person other)
{
return other != null && other.Name == Name && other.Age == Age;
}
}
This will allow you to do:
Person savedPerson = ...
Person importedPerson = ...
bool hasChanged = !savedPerson.Equals(importedPerson);
If, on the other hand, you do have lots of different definitions of equality for different circumstances, your best bet would be to write up different IEqualityComparer<T>
implementations. Here's a sample implementation:
public class AgeComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return (x == null || y == null) ? x == y : x.Age == y.Age;
}
public int GetHashCode(Person obj)
{
return obj == null ? 0 : obj.Age;
}
}
In this case, the check will look like:
Person savedPerson = ...
Person importedPerson = ...
IEqualityComparer<Person> comparer = ...
bool hasChanged = !comparer.Equals(savedPerson, importedPerson);
Upvotes: 10
Reputation: 8421
Yes you will need your type to implement IComparable. Here is a sample on how to do it.
Upvotes: 0
Reputation: 1770
That is about how you want to perform compare operation. You can do the operation in both ways:
public void Method()
{
Foo p1 = new Foo();
Foo p2 = new Foo();
p1.CompareTo(p2);
FooComparer c = new FooComparer();
c.Compare(p1, p2);
}
class Foo : IComparable
{
public int CompareTo(object obj)
{
throw new NotImplementedException();
}
}
class FooComparer : IComparer<Foo>
{
public int Compare(Foo x, Foo y)
{
throw new NotImplementedException();
}
}
I prefer using IComparer as seperation of concerns. Foo is my class, I have some busines needs on it. If I want to compare some Foos, I use FooComparer. For your situation you can return the number of changed properties from Compare method. If Compare method return 0. Then two Foos are same.
As I said. That is completely how you want to perform the action I think. Overriding Equality Operators are also good solution. Implementing IEqualityComparer<T>
is another solution.
Upvotes: 0
Reputation: 141
An alternative to implementing the IComparable interface would be to override the Equals and GetHashCode functions.
Upvotes: 0
Reputation: 4231
As you have alluded to IComparable is typically used for sorting.
In this case you would want to overload the comparison operator: ==
Because the reverse comparison should also be valid, this implies you must also overload the != operator.
When you overload == and !- you are also expected to override Equals and GetHashCode.
A decent C# book should explain the details.
Upvotes: 0