Simplify Overriding Equals (), GetHashCode () en C # para una mejor mantenibilidad

Me encuentro a mí mismo anulandoEquals() yGetHashCode() con frecuencia para implementar la semántica de que los objetos comerciales con valores de propiedad idénticos son iguales. Eso lleva a un código que es repetitivo para escribir y frágil para mantener (la propiedad se agrega y una / ambas modificaciones no se actualizan).

El código termina pareciéndose a esto (los comentarios sobre la implementación son bienvenidos):

public override bool Equals(object obj)
{
    if (object.ReferenceEquals(this, obj)) return true;

    MyDerived other = obj as MyDerived;

    if (other == null) return false;

    bool baseEquals = base.Equals((MyBase)other);
    return (baseEquals && 
        this.MyIntProp == other.MyIntProp && 
        this.MyStringProp == other.MyStringProp && 
        this.MyCollectionProp.IsEquivalentTo(other.MyCollectionProp) && // See http://stackoverflow.com/a/9658866/141172
        this.MyContainedClass.Equals(other.MyContainedClass));
}

public override int GetHashCode()
{
    int hashOfMyCollectionProp = 0;
    // http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/
    // BUT... is it worth the extra math given that elem.GetHashCode() should be well-distributed?
    int bitSpreader = 31; 
    foreach (var elem in MyCollectionProp)
    {
        hashOfMyCollectionProp = spreader * elem.GetHashCode();
        bitSpreader *= 31;
    }
    return base.GetHashCode() ^ // ^ is a good combiner IF the combined values are well distributed
        MyIntProp.GetHashCode() ^ 
        (MyStringProp == null ? 0 : MyStringProp.GetHashValue()) ^
        (MyContainedClass == null ? 0 : MyContainedClass.GetHashValue()) ^
        hashOfMyCollectionProp;
}

Mis pregunta

¿Es el sonido del patrón de implementación?Es adecuado dado que los valores de los componentes contribuyentes están bien distribuidos? ¿Necesito multiplicar por 31 a la N cuando combino elementos de colección dado que su hash está bien distribuido? Parece que este código podría resumirse en un código que utiliza la reflexión para determinar las propiedades públicas, crea un árbol de expresión que coincide con la solución codificada a mano y ejecuta el árbol de expresión según sea necesario. ¿Ese enfoque parece razonable? ¿Existe alguna implementación existente en alguna parte?

Respuestas a la pregunta(6)

Su respuesta a la pregunta