tienes razón, esto es una gran cantidad de código de la caldera de la placa, y hay que poner en práctica todo por separado.
lo haría recomendar:
- Si usted va a poner en práctica la igualdad de valor alguno, anular y
GetHashCode
Equals(object)
- la creación de sobrecargas para == e implementar IEquatable<T>
sin hacer que podría resultar en un comportamiento muy inesperado
- yo siempre aplicar
IEquatable<T>
si estás anulando Equals(object)
y GetHashCode
- sólo sobrecargar el operador == más raramente
- la implementación de la igualdad de clases sin sellar correctamente es difícil, y todavía puede producir resultados sorprendentes/indeseables. Si necesita igualdad para los tipos en una jerarquía, implemente
IEqualityComparer<T>
expresando la comparación que le interesa.
- La igualdad para los tipos mutables generalmente es una mala idea, ya que dos objetos pueden ser iguales y luego desiguales más adelante ...si un objeto está mutado (de una manera que afecta la igualdad) después de haber sido utilizado como clave en una tabla hash, no podrá encontrarlo nuevamente.
- Parte de la placa de la caldera es ligeramente diferente para las estructuras ... pero como Marc, rara vez escribo mis propias estructuras.
Aquí está un ejemplo de implementación:
using System;
public sealed class Foo : IEquatable<Foo>
{
private readonly string name;
public string Name { get { return name; } }
private readonly int value;
public int Value { get { return value; } }
public Foo(string name, int value)
{
this.name = name;
this.value = value;
}
public override bool Equals(object other)
{
return Equals(other as Foo);
}
public override int GetHashCode()
{
int hash = 17;
hash = hash * 31 + (name == null ? 0 : name.GetHashCode());
hash = hash * 31 + value;
return hash;
}
public bool Equals(Foo other)
{
if ((object) other == null)
{
return false;
}
return name == other.name && value == other.value;
}
public static bool operator ==(Foo left, Foo right)
{
return object.Equals(left, right);
}
public static bool operator !=(Foo left, Foo right)
{
return !(left == right);
}
}
Y sí, eso es una diablos de un montón de repetitivo, muy poco de lo que cambia entre las implementaciones :(
La implementación de ==
es ligeramente menos eficiente de lo que podría ser, ya que llamará a Equals(object)
que necesita hacer la verificación de tipo dinámico ... pero la alternativa es aún más placa de caldera, como esta:
public static bool operator ==(Foo left, Foo right)
{
if ((object) left == (object) right)
{
return true;
}
// "right" being null is covered in left.Equals(right)
if ((object) left == null)
{
return false;
}
return left.Equals(right);
}
^^ Su cada puesto es un capítulo de aprendizaje C# .. :) – Dienekes
2 sugerencias menores para el segundo bloque de código: 1) ¿No deberías mover '(objeto) izquierda == (objeto) derecho' de' == 'a' Iguales' genéricos? Entonces, ¿eso da la velocidad (por supuesto depende, pero suponiendo el peor de los casos) la comprobación de la igualdad de referencia incluso para el método genérico "Igual"? 2) no necesita la segunda comprobación nula '(objeto) derecha == nulo' en' == 'ya que básicamente hace eso en' Iguales' genéricos. Ver mi publicación .. – nawfal
@nawfal: No creo que tenga mucho sentido hacerlo en el caso genérico 'Equals'; de todos modos será rápido en los casos en que * es * verdadero, y para los casos en que * no es * verdadero, está agregando un cheque adicional sin beneficio. En cuanto a la parte nula, eso requeriría la verificación dinámica de tipo nuevamente. Sí, podría argumentar a favor de ambos, pero estoy satisfecho con lo que escribí hace dos años ... –