how do i correctly impl GetHashCode for syntactically equal object

G

Guest

I have some business objects which overrides Equals to provide syntax
equality instead of just reference equality. Overriding equals gives me a
warning that i must override GetHashcode(). Msdn says this about implementing
hashcode:

(1)If two objects of the same type represent the same value, the hash
function must return the same constant value for either object.
(2)For the best performance, a hash function must generate a random
distribution for all input.
(3)The hash function must return exactly the same value regardless of any
changes that are made to the object.

Since object.GetHashCode() is implemented using the object SYNCBLOC (i
think), it fall short when syntax equality is introduced (see req nr 1). The
problem is that i can't really se how i can combine req 1 and 3 if the object
is not immutable. Req 3 (as i interpret it) basically states that the
hashcode must be calculated based on member variables when the object is
initialized and it should not reflect changes to the object data. Now
consider the following: two objects are initialised with different values and
their hashes are calculated. We change the values of one of the objects so
that both objects are syntactically equal. Since the hashcodes we calculated
were based on the initialized values, req 1 is breached and the new
implementation is as bad as the original. Is there a way to implement
GetHashcode() correctly for mutable syntactically equal reference types?
Perhaps i am misinterpreting the implementation guidelines?
 
J

Joerg Jooss

Hello MariusI,
I have some business objects which overrides Equals to provide syntax
equality instead of just reference equality. Overriding equals gives
me a warning that i must override GetHashcode(). Msdn says this about
implementing hashcode:

(1)If two objects of the same type represent the same value, the hash
function must return the same constant value for either object. (2)For
the best performance, a hash function must generate a random
distribution for all input. (3)The hash function must return exactly
the same value regardless of any changes that are made to the object.

Since object.GetHashCode() is implemented using the object SYNCBLOC (i
think), it fall short when syntax equality is introduced (see req nr
1). The problem is that i can't really se how i can combine req 1 and
3 if the object is not immutable. Req 3 (as i interpret it) basically
states that the hashcode must be calculated based on member variables
when the object is initialized and it should not reflect changes to
the object data. Now consider the following: two objects are
initialised with different values and their hashes are calculated. We
change the values of one of the objects so that both objects are
syntactically equal. Since the hashcodes we calculated were based on
the initialized values, req 1 is breached and the new implementation
is as bad as the original. Is there a way to implement GetHashcode()
correctly for mutable syntactically equal reference types? Perhaps i
am misinterpreting the implementation guidelines?

Equality is a *semantical* concept.

What these rules basically imply that a type must have a "basic" identity
which cannot be changed after its construction in order to be support Equals()
and GetHashCode(). Think of a Person object that lives in a RDBMS like SQL
Server:

public class Person {
private int primaryKey;
private string firstName;
private string lastName;
private DateTime age;

// And similar named public Properties PrimaryKey, FirstName, LastName, Age
}

The following version of Person does not allow for such a basic identity:

public class Person {
// private fields as above

public Person() {}

public PrimaryKey { get; set; }
}

This basically wraps arbitrary records from the database, and can switch
identities each time you assign it a new PrimaryKey. This kind of class cannot
support both rules (1) and (3).

So what you need is to make such classes partially immutable:

public class Person {
// private fields as above, but
private readonly int primaryKey;

public Person(PrimaryKey primaryKey) {
this.primaryKey = primaryKey;
}

public PrimaryKey { get; }

// Equals() and GetHashCode()
}

This also implies that hash code calculation only uses immutable members
of the object.

Cheers,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top