public class Address{
public string ContactName {get; private set;}
public string Company {get; private set;}
//...
public string Zip {get; private set;}
}
I’d like to implement a notion of distinct addresses, so I overrode Equals() to test for case-insensitive equality in all of the fields (as these are US addresses, I used Ordinal instead of InvariantCulture for maximum performance):
public override bool Equals(Object obj){
if (obj == null || this.GetType() != obj.GetType())
return false;
Address o = (Address)obj;
return
(string.Compare(this.ContactName, o.ContactName, StringComparison.OrdinalIgnoreCase) == 0) &&
(string.Compare(this.Company, o.Company, StringComparison.OrdinalIgnoreCase) == 0)
// ...
(string.Compare(this.Zip, o.Zip, StringComparison.OrdinalIgnoreCase) == 0)
}
I’d like to write a GetHashCode() similarly like so (ignore the concatenation inefficiency for the moment):
public override int GetHashCode(){
return (this.contactName + this.address1 + this.zip).ToLowerOrdinal().GetHashCode();
}
but that doesn’t exist. What should I use instead? Or should I just use InvariantCulture in my Equals() method?
(I’m thinking .ToLowerInvariant().GetHashCode(), but I’m not 100% sure that InvariantCulture can’t decide that an identical character (such as an accent) has a different meaning in another context.)
Two unequal objects can have the same hashcode. Though two equal objects should never have different hashcodes. If you use InvariantCulture for your hashcode it will still be correct as far as the contract for Equals goes if it’s implemented in terms of OrdinalIgnoreCase.
From the documentation on StringComparer.OrdinalIgnoreCase (emphasis mine):
http://msdn.microsoft.com/en-us/library/system.stringcomparer.ordinalignorecase.aspx