Lista <T> .Contains y T []. Contiene comportarse de manera diferente
Di que tengo esta clase:
public class Animal : IEquatable<Animal>
{
public string Name { get; set; }
public bool Equals(Animal other)
{
return Name.Equals(other.Name);
}
public override bool Equals(object obj)
{
return Equals((Animal)obj);
}
public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
}
Esta es la prueba:
var animals = new[] { new Animal { Name = "Fred" } };
Ahora, cuando lo hago:
animals.ToList().Contains(new Animal { Name = "Fred" });
llama a la derechagenéricoEquals
sobrecarga. El problema es con los tipos de matriz. Supongamos que yo hago:
animals.Contains(new Animal { Name = "Fred" });
llamano genéricoEquals
método. ActualmenteT[]
no exponeICollection<T>.Contains
método. En el caso anteriorIEnumerable<Animal>.Contains
sobrecarga de extensión se llama que a su vez llama a laICollection<T>.Contains
. Aquí es cómoIEnumerable<T>.Contains
está implementado:
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value)
{
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null)
{
return collection.Contains(value); //this is where it gets done for arrays
}
return source.Contains(value, null);
}
Así que mis preguntas son:
Por quédeberíaList<T>.Contains
yT[].Contains
comportarse de manera diferente? En otras palabras, ¿por qué es el ex llamado elgenéricoEquals
y eleste último no genéricoEquals
A pesar de que ambas colecciones son genéricas.?¿Hay alguna manera de que pueda verT[].Contains
¿implementación?Editar: ¿Por qué importa o por qué estoy preguntando esto?
Se tropieza con uno en caso de que ella se olvide de anularno genéricoEquals
al implementarIEquatable<T>
en cuyo caso llamadas comoT[].Contains
Hace una verificación de igualdad referencial. Especialmente cuando ella esperatodas las colecciones genéricas para operar engenéricoEquals
.
Pierdes todos los beneficios de la implementación.IEquatable<T>
(aunque no es un desastre para tipos de referencia).
Como se señaló en los comentarios, solo me interesa conocer los detalles internos y las opciones de diseño. No hay otra situación genérica en la que pueda pensarno genéricoEquals
Se preferirá, sea cualquieraList<T>
o conjunto basado (Dictionary<K,V>
etc) operaciones. Peor aún,si Animal hubiera sido una estructura, Animal []. Contiene las llamadasgenéricoEquals
, todo lo que hace que la implementación de T [] sea un poco extraña, algo que los desarrolladores deberían saber.
Nota: La versión genérica deEquals
se llama solo cuando la claseimplementosIEquatable<T>
. Si la clase no se implementa.IEquatable<T>
, sobrecarga no genérica deEquals
se llama independientemente de si se llama porList<T>.Contains
oT[].Contains
.