nat
nat

Reputation: 2197

checking two object instances to see if they are the same

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

Answers (5)

Ani
Ani

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

Vinay B R
Vinay B R

Reputation: 8421

Yes you will need your type to implement IComparable. Here is a sample on how to do it.

Upvotes: 0

Musa Hafalir
Musa Hafalir

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

CoderSivu
CoderSivu

Reputation: 141

An alternative to implementing the IComparable interface would be to override the Equals and GetHashCode functions.

Upvotes: 0

Sisyphus
Sisyphus

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

Related Questions