tags:

views:

986

answers:

3

I have a Customer class.

public class Customer
{
    private string _id;
    private string _name;
    // some more properties follow

I am inheriting the EqualityComparer form MyEqualityComparer(of Customer).
This I am intending to use in LINQ queries.
MyEqualityComparer is intended for partial check between two objects.
If the customer.id and customer.name matches I treat the objects the equal.

public class MyComparer : System.Collections.Generic.EqualityComparer<Customer>
{
    public override bool Equals(Customer x, Customer y)
    {
        if (x.Id == y.Id && x.Name == y.Name)
            return true;
        else
            return false;
    }

    public override int GetHashCode(Customer obj)
    {
        return string.Concat(obj.Id,obj.Name).GetHashCode();
    }

}

I referred to generating hashcode.
I am little unsure about concatenating strings and using that as a hashcode.
Is this safe and sound what I am trying to do ?

+3  A: 

You should see it from the perspective of possible "collisions", e.g. when two different objects get the same hash code. This could be the case with such pairs as "1,2any" and "12, any", the values in the pairs being "id" and "name". If this is not possible with your data, you're good to go. Otherwise you can change it to something like:

return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
liggett78
don't forget to null check Id and Name
Mike Two
Using an XOR creates collisions in quite a few situations, unfortunately. See http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-systemobjectgethashcode#263416. It may well be okay in the case of Name/ID, but it's not a good idea in general.
Jon Skeet
+3  A: 

See this question on hashcodes for a pretty simple way to return one hashcode based on multiple fields.

Having said that, I wouldn't derive from EqualityComparer<T> myself - I'd just implement IEqualityComparer<T> directly. I'm not sure what value EqualityComparer<T> is really giving you here, other than also implementing the non-generic IEqualityComparer.

A couple more things:

  • You should handle nullity in Equals
  • Your present Equals code can be simplified to:

    return x.Id == y.Id && x.Name == y.Name;
    

A fuller implementation of Equals might be:

public override bool Equals(Customer x, Customer y)
{
    if (object.ReferenceEquals(x, y))
    {
        return true;
    }
    if (x == null || y == null)
    {
        return false;
    }
    return x.Id == y.Id && x.Name == y.Name;
}
Jon Skeet
+1  A: 

Resharper (fantastic refactoring plugin from JetBrains) thinks it should be:

public override int GetHashCode(Customer obj)
{
    unchecked
    {
        return ((obj.Id != null ? obj.Id.GetHashCode() : 0) * 397) 
            ^ (obj.Name != null ? obj.Name.GetHashCode() : 0);
    }
}

I have to admit I almost always just let Resharper generate the equality and hash code implementations for me. I've tested their implementation a great deal and found it to be as good if not better than anything I'd write by hand. So I'll usually take the implementation I don't have to type.

Mike Two
Any reason for picking 397 other than prime ?
Biswanath
I think it is just meant to be big enough to put the first part of the hashcode in the higher bits of the end result. Resharper used to use 29. I can't say I know if there is a solid theory or if it was just chosen through experiement.
Mike Two