Quiero entender los escenarios en los que se deben usar IEqualityComparer<T>
y IEquatable<T>
. La documentación de MSDN para ambos se ve muy similar.¿Cuál es la diferencia entre IEqualityComparer <T> e IEquatable <T>?
Respuesta
IEqualityComparer<T>
es una interfaz para un objeto que realiza la comparación en dos objetos del tipo T
.
IEquatable<T>
es para un objeto del tipo T
para que pueda compararse con otro.
+1 _IEquatable es para un objeto para que se pueda comparar con otro_ ** del mismo tipo ** – gdoron
Simple, conciso y fácil de comprender – Tilak
Ditto @Tilak .... No se necesita más explicación – rajibdotnet
Uno compara dos T
s. El otro puede compararse con otros T
s. Usualmente, solo necesitarás usar uno a la vez, no ambos.
IEqualityComparer es para usar cuando la igualdad de dos objetos se implementa externamente, p. si quería definir un comparador para dos tipos para los que no tenía la fuente, o para casos donde la igualdad entre dos cosas solo tiene sentido en un contexto limitado.
IEtabletable es para el objeto en sí (el que se compara por la igualdad) para implementar.
Usted es el único que planteó realmente el problema "Plugging in Equality" (uso externo). Más 1. –
Ya tiene la definición básica de que son. En resumen, si implementa IEquatable<T>
en la clase T
, el método Equals
en un objeto de tipo T
le indica si el objeto en sí (el que se prueba para la igualdad) es igual a otra instancia del mismo tipo T
. Mientras que, IEqualityComparer<T>
es para probar la igualdad de dos instancias de T
, generalmente fuera del alcance de las instancias de T
.
En cuanto a lo que son para puede ser confuso al principio. A partir de la definición, debe quedar claro que, por lo tanto, IEquatable<T>
(definido en la clase T
en sí misma) debe ser el estándar de facto para representar la singularidad de sus objetos/instancias. HashSet<T>
, Dictionary<T, U>
(teniendo en cuenta GetHashCode
se reemplaza también), Contains
en List<T>
etc. hacer uso de esto. Implementar IEqualityComparer<T>
en T
no ayuda en los casos generales mencionados anteriormente. Posteriormente, hay poco valor para implementar IEquatable<T>
en cualquier otra clase que no sea T
. Esto:
class MyClass : IEquatable<T>
rara vez tiene sentido.
Por otro lado
class T : IEquatable<T>
{
//override ==, !=, GetHashCode and non generic Equals as well
public bool Equals(T other)
{
//....
}
}
es como debe hacerse.
IEqualityComparer<T>
puede ser útil cuando necesita una validación de igualdad personalizada, pero no como una regla general. Por ejemplo, en una clase de Person
en algún momento, es posible que deba probar la igualdad de dos personas en función de su edad.En ese caso se puede hacer:
class Person
{
public int Age;
}
class AgeEqualityTester : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.Age == y.Age;
}
public int GetHashCode(Person obj)
{
return obj.Age.GetHashCode;
}
}
Para probarlos, tratar
var people = new Person[] { new Person { age = 23 } };
Person p = new Person() { age = 23 };
print people.Contains(p); //false;
print people.Contains(p, new AgeEqualityTester()); //true
Del mismo modo IEqualityComparer<T>
en T
no tiene sentido.
class Person : IEqualityComparer<Person>
Verdadero esto funciona, pero no se ve bien a los ojos y derrota la lógica.
Normalmente lo que necesita es IEquatable<T>
. También idealmente puede tener solo un IEquatable<T>
, mientras que es posible un múltiplo IEqualityComparer<T>
según diferentes criterios.
El IEqualityComparer<T>
y IEquatable<T>
son exactamente análoga a Comparer<T>
y IComparable<T>
que se utilizan para propósitos de comparación en lugar de equiparar; un buen hilo here donde escribí la misma respuesta :)
'public int GetHashCode (Person obj)' debe devolver 'obj.GetHashCode()' –
@HristoYankov debe devolver 'obj.Age.GetHashCode'. editará – nawfal
Por favor, explique por qué el comparador debe hacer tal suposición acerca de cuál es el hash del objeto que compara? Su comparador no sabe cómo Person calcula su Hash, ¿por qué anularía eso? –
la hora de decidir si se debe utilizar o IEquatable<T>
IEqualityComparer<T>
, uno podría preguntar:
¿Hay una forma preferida de poner a prueba dos instancias de
T
por la igualdad, o hay varias formas igualmente válidas?
Si sólo hay una manera de probar dos instancias de
T
por la igualdad, o si se prefiere uno de varios métodos, a continuación,IEquatable<T>
sería la opción correcta: se supone Esta interfaz para ser implementado solamente porT
en sí, de modo que una instancia deT
tiene conocimiento interno de cómo compararse con otra instancia deT
.Por otro lado, si hay varios métodos igualmente razonables de la comparación de dos
T
s para la igualdad,IEqualityComparer<T>
parece más adecuado: Esta interfaz no está destinado a ser implementado porT
en sí, sino por otras clases "externos" . Por lo tanto, al probar dos instancias deT
para la igualdad, porqueT
no tiene una comprensión interna de la igualdad, tendrá que hacer una elección explícita de una instanciaIEqualityComparer<T>
que realice la prueba de acuerdo con sus requisitos específicos.
Ejemplo:
Vamos a considerar estos dos tipos (que se supone que tienen value semantics):
interface IIntPoint : IEquatable<IIntPoint>
{
int X { get; }
int Y { get; }
}
interface IDoublePoint // does not inherit IEquatable<IDoublePoint>; see below.
{
double X { get; }
double Y { get; }
}
¿Por qué sólo uno de estos tipos heredar IEquatable<>
, pero no el otro ?
En teoría, solo hay una forma sensata de comparar dos instancias de cualquier tipo: Son iguales si las propiedades X
y Y
en ambas instancias son iguales.Según este pensamiento, ambos tipos deberían implementar IEquatable<>
, porque no parece probable que existan otras formas significativas de hacer una prueba de igualdad.
El problema aquí es que comparing floating-point numbers for equality might not work as expected, due to minute rounding errors. Existen diferentes métodos para comparar números de coma flotante para near-equality, cada uno con ventajas específicas y compensaciones, y es posible que desee poder elegir qué método es el adecuado.
sealed class DoublePointNearEqualityComparerByTolerance : IEqualityComparer<IDoublePoint>
{
public DoublePointNearEqualityComparerByTolerance(double tolerance) { … }
…
public bool Equals(IDoublePoint a, IDoublePoint b)
{
return Math.Abs(a.X - b.X) <= tolerance && Math.Abs(a.Y - b.Y) <= tolerance;
}
…
}
Tenga en cuenta que la página a la que he vinculado (arriba) establece explícitamente que esta prueba para near-equality tiene algunos puntos débiles. Como se trata de una implementación IEqualityComparer<T>
, simplemente puede cambiarla si no es lo suficientemente buena para sus propósitos.
El método de comparación sugerido para probar la igualdad de doble punto está roto, ya que cualquier implementación legítima de 'IEqualityComparer
Un mejor ejemplo serían las comparaciones entre cadenas. Tiene sentido tener un método de comparación de cadenas que considere las cadenas como iguales solo si contienen la misma secuencia de bytes, pero hay otros métodos de comparación útiles * que también constituyen relaciones de equivalencia *, como las comparaciones insensibles a mayúsculas y minúsculas.Tenga en cuenta que un 'IEqualityComparer
@supercat, gracias por los valiosos comentarios. Es probable que no repase la revisión de mi respuesta en los próximos días, así que, si lo desea, puede editar como lo considere oportuno. – stakx
- 1. ¿Cuál es la diferencia entre las interfaces IComparable e IEquatable?
- 2. ¿Cuál es la diferencia entre <? super E> y <? extends E>?
- 3. ¿Cuál es la diferencia entre <% %> y <%=%>?
- 4. ¿Cuál es la diferencia entre <%# %> y <%= %>?
- 5. En ASP.Net, ¿cuál es la diferencia entre <% = y <% #
- 6. ¿Cuál es la diferencia entre ofstream "<<" y Write
- 7. ¿Cuál es la diferencia entre List <string> e IEnumerable <String>?
- 8. ¿Por qué necesitamos la interfaz IEqualityComparer, IEqualityComparer <T>?
- 9. ¿Cuál es la diferencia entre IEquatable y simplemente anulando Object.Equals()?
- 10. ¿Cuál es la diferencia entre <%: y <% = y <% # en aspx?
- 11. ¿Cuál es la diferencia entre `=` y `<-` en R?
- 12. ¿Cuál es la diferencia entre "<>" y "! ="?
- 13. Cuál es la diferencia entre mysqlimport y mysql <dbfile.sql
- 14. cuál es la diferencia entre '! =' Y '<>' en MySQL
- 15. diferencia entre <%! %> y <% %>
- 16. ¿cuál es la diferencia entre la lista <> y el diccionario <> en C#
- 17. Java: ¿Cuál es la diferencia entre <init> y <clinit>?
- 18. ¿Cuál es la diferencia entre cout << cout y cout << y cout en C++?
- 19. Diferencia entre IEnumerable e IEnumerable <T>?
- 20. <% $, <% @, <% =, <% # ... ¿cuál es el problema?
- 21. ¿Cuál es la diferencia entre <% # y <% = en ASP.NET MVC?
- 22. ¿Cuál es la diferencia entre <system.web> y <system.webServer>?
- 23. ¿Cuál es la diferencia entre <% # Bind ("")%> y <% # Eval ("")%> en ASP.NET?
- 24. ¿Cuál es la diferencia entre <% %> y <%= %> en ASP.NET MVC
- 25. ¿Cuál es la diferencia entre Func <T, TResult> y Converter <TInput, TOutput>?
- 26. Cuál es la diferencia entre <#eval y <#bind en asp.net
- 27. WSDL: cuál es la diferencia entre <binding> y <portType>
- 28. ¿Cuál es la diferencia entre las etiquetas de apertura <% # y <% =?
- 29. ¿Cuál es la diferencia entre "plantilla <class T>" y "plantilla <typename T>"?
- 30. ¿Cuál es la diferencia entre <pubDate> y <lastBuildDate> en RSS?
¡esta pregunta necesita más votos positivos! – nawfal
[MSDN sez:] (https://msdn.microsoft.com/en-us/library/ms132151 (v = vs.110) .aspx) "Esta interfaz permite la implementación de la comparación de igualdad personalizada ** para colecciones. * * "que por supuesto se infiere en la respuesta seleccionada. MSDN también recomienda heredar 'EqualityComparer' en lugar de implementar la interfaz "porque' EqualityComparer 'prueba la igualdad usando' IEquatable ' –
radarbob
... lo anterior sugiere que debo crear una colección personalizada para cualquier' T' que implemente 'IEquatable'. ¿Una colección como 'List ' tiene algún tipo de error sutil? –
radarbob