tipos - c#Cómo encontrar si dos objetos son iguales
metodo equals (6)
Para dos objetos cualquiera, la igualdad de objeto implica igualdad de código hash, sin embargo , la igualdad de código hash no implica igualdad de objeto. Desde Object.GetHashCode
en MSDN:
Una función hash debe tener las siguientes propiedades:
Si dos objetos se comparan como iguales, el método GetHashCode para cada objeto debe devolver el mismo valor. Sin embargo, si dos objetos no se pueden comparar como iguales, los métodos GetHashCode para los dos objetos no tienen que devolver valores diferentes.
En otras palabras, tu Equals
está mal escrito. Debería ser algo así como:
public override bool Equals(object obj)
{
Test other = obj as Test;
if (other == null)
return false;
return (Value == other.Value)
&& (String1 == other.String1)
&& (String2 == other.String2);
}
GetHashCode
es bueno para colecciones (como Dictionary<K, V>
) para determinar rápidamente la igualdad aproximada. Equals
es para comparar si dos objetos son realmente iguales.
Necesito saber la mejor manera de comparar dos objetos y averiguar si hay igualdad. Estoy anulando tanto GethashCode como Equals. Entonces una clase básica se ve así:
public class Test
{
public int Value { get; set; }
public string String1 { get; set; }
public string String2 { get; set; }
public override int GetHashCode()
{
return Value ^ String1.GetHashCode() ^ String2.GetHashCode();
}
public override bool Equals( object obj )
{
return GetHashCode() == obj.GetHashCode();
}
}
Entonces para fines de prueba creé dos objetos:
Test t = new Test()
{
Value = 1,
String1 ="One",
String2 = "One"
};
Test t2 = new Test()
{
Value = 1,
String1 = "Two",
String2 = "Two"
};
bool areEqual = t.Equals( t2 );
Al probar esto, Equal devuelve un evento verdadero aunque ambos objetos son diferentes. Me doy cuenta de que esto se debe a que String1 y String2 tienen el mismo valor en cada objeto y, por lo tanto, se anulan mutuamente cuando se procesan hash.
¿Hay una forma mejor de eliminar el objeto hash que el método que tengo que resolverá mi problema?
Puede serializar los dos objetos en JSON, luego comparar las dos cadenas para ver si son iguales.
Por ejemplo
JavaSriptSerializer serialiser = new JavaScriptSerializer();
string t1String = serialiser.Serialize(t);
string t2String = serialiser.Serialize(t2);
if(t1String == t2String)
return true; //they are equal
else
return false;
Su método de igualdad actual está roto: hay más valores que posibles códigos hash. Es completamente razonable (y esperado) que ocasionalmente tengas valores que son desiguales pero dan el mismo hash. Igual debe verificar los valores reales :
public override bool Equals(object obj)
{
Test test = obj as Test;
if (obj == null)
{
return false;
}
return Value == test.Value &&
String1 == test.String1 &&
String2 == test.String2;
}
Algunas cosas a tener en cuenta:
Su forma de generar el
String2
dará el mismo valor para cualquierValue
fijo siString2
yString2
son iguales; también explotará siString2
oString2
es nulo. Este es un aspecto desafortunado de usar XOR para hash. Prefiero algo como esto:// Put this extension method in a utility class somewhere public static int SafeGetHashCode<T>(this T value) where T : class { return value == null ? 0 : value.GetHashCode(); } // and this in your actual class public override int GetHashCode() { int hash = 19; hash = hash * 31 + Value; hash = hash * 31 + String1.SafeGetHashCode(); hash = hash * 31 + String2.SafeGetHashCode(); return hash; }
En términos generales, la igualdad se vuelve engañosa cuando se involucra la herencia. Es posible que desee considerar el sellado de su clase.
Es posible que también desee implementar
IEquatable<Test>
Tu Equals
es incorrecta, eso debería definir lo que significa que dos cosas sean iguales, y tener el mismo código hash no significa igualdad (sin embargo, un código hash diferente significa no igualdad). Si "igualdad" significa "ambas cadenas son iguales en pares", entonces prueba eso.
Re a mejor hash; xor es notorio por esto, ya que es trivial obtener 0 por xor un valor consigo mismo. Un mejor enfoque puede ser algo como:
int i = 0x65407627;
i = (i * -1521134295) + Value.GetHashCode();
i = (i * -1521134295) + (String1 == null ? 0 : String1.GetHashCode());
i = (i * -1521134295) + (String2 == null ? 0 : String2.GetHashCode());
return i;
sencillo
Object.Equals(obj1, obj2);
would not a function Equals siempre prueba solo contra el mismo tipo, no debería ser:
//override
public bool Equals(Test other)//(object obj)
{
//return GetHashCode() == obj.GetHashCode();
return (Value == other.Value) &&
(String1 == other.String1) &&
(String2 == other.String2);
}
recuerdos Vaya