Equality Members
Thursday, June 16, 2011 11:48 AM
I was watching a presentation today and noticed an implementation of GetHashCode() that was... less than perfect :)
For those without the luxury of Resharper, I thought I'd create a few examples of implementing the equality members. For a refresher on defining equality, see this MSDN article. Note that, while technically optional, it is recommended to overload the == and != operators too.
public class IntPrimaryKey : IEquatable<IntPrimaryKey> { public int PrimaryKey { get; set; } public bool Equals(IntPrimaryKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return PrimaryKey == other.PrimaryKey; } public override bool Equals(object obj) { return Equals(obj as IntPrimaryKey); } public override int GetHashCode() { return PrimaryKey; } } public class StringPrimaryKey : IEquatable<StringPrimaryKey> { public string PrimaryKey { get; set; } public bool Equals(StringPrimaryKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(PrimaryKey, other.PrimaryKey); } public override bool Equals(object obj) { return Equals(obj as StringPrimaryKey); } public override int GetHashCode() { return PrimaryKey == null ? 0 : PrimaryKey.GetHashCode(); } } public class MultiNumberPrimaryKey : IEquatable<MultiNumberPrimaryKey> { public int PrimaryKey1 { get; set; } public int PrimaryKey2 { get; set; } public bool Equals(MultiNumberPrimaryKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return PrimaryKey1 == other.PrimaryKey1 && PrimaryKey2 == other.PrimaryKey2; } public override bool Equals(object obj) { return Equals(obj as MultiNumberPrimaryKey); } public override int GetHashCode() { unchecked { return (PrimaryKey1 * 397) ^ PrimaryKey2; } } } public class MultiStringPrimaryKey : IEquatable<MultiStringPrimaryKey> { public string PrimaryKey1 { get; set; } public string PrimaryKey2 { get; set; } public bool Equals(MultiStringPrimaryKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(PrimaryKey1, other.PrimaryKey1) && Equals(PrimaryKey2, other.PrimaryKey2); } public override bool Equals(object obj) { return Equals(obj as MultiStringPrimaryKey); } public override int GetHashCode() { unchecked { return ((PrimaryKey1 == null ? 0 : PrimaryKey1.GetHashCode()) * 397) ^ (PrimaryKey2 == null ? 0 : PrimaryKey2.GetHashCode()); } } } public class MultiMixedPrimaryKey : IEquatable<MultiMixedPrimaryKey> { public int PrimaryKey1 { get; set; } public string PrimaryKey2 { get; set; } public bool Equals(MultiMixedPrimaryKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return PrimaryKey1 == other.PrimaryKey1 && Equals(PrimaryKey2, other.PrimaryKey2); } public override bool Equals(object obj) { return Equals(obj as MultiMixedPrimaryKey); } public override int GetHashCode() { unchecked { return (PrimaryKey1 * 397) ^ (PrimaryKey2 == null ? 0 : PrimaryKey2.GetHashCode()); } } } public class MultiPrimaryKey : IEquatable<MultiPrimaryKey> { public int PrimaryKey1 { get; set; } public int PrimaryKey2 { get; set; } public int PrimaryKey3 { get; set; } public int PrimaryKey4 { get; set; } public bool Equals(MultiPrimaryKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return PrimaryKey1 == other.PrimaryKey1 && PrimaryKey2 == other.PrimaryKey2 && PrimaryKey3 == other.PrimaryKey3 && PrimaryKey4 == other.PrimaryKey4; } public override bool Equals(object obj) { return Equals(obj as MultiPrimaryKey); } public override int GetHashCode() { unchecked { int result = PrimaryKey1; result = (result * 397) ^ PrimaryKey2; result = (result * 397) ^ PrimaryKey3; result = (result * 397) ^ PrimaryKey4; return result; } } } public class MultiPrimaryKey2 : IEquatable<MultiPrimaryKey2> { public string PrimaryKey1 { get; set; } public string PrimaryKey2 { get; set; } public string PrimaryKey3 { get; set; } public string PrimaryKey4 { get; set; } public bool Equals(MultiPrimaryKey2 other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(PrimaryKey1, other.PrimaryKey1) && Equals(PrimaryKey2, other.PrimaryKey2) && Equals(PrimaryKey3, other.PrimaryKey3) && Equals(PrimaryKey4, other.PrimaryKey4); } public override bool Equals(object obj) { return Equals(obj as MultiPrimaryKey2); } public override int GetHashCode() { unchecked { int result = PrimaryKey1 == null ? 0 : PrimaryKey1.GetHashCode(); result = (result * 397) ^ (PrimaryKey2 == null ? 0 : PrimaryKey2.GetHashCode()); result = (result * 397) ^ (PrimaryKey3 == null ? 0 : PrimaryKey3.GetHashCode()); result = (result * 397) ^ (PrimaryKey4 == null ? 0 : PrimaryKey4.GetHashCode()); return result; } } }
Tags: .net, bestpractices