Lista <T>. Zawiera i T []. Zawiera inne zachowanie
Powiedz, że mam tę klasę:
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();
}
}
To jest test:
var animals = new[] { new Animal { Name = "Fred" } };
Teraz, kiedy to robię:
animals.ToList().Contains(new Animal { Name = "Fred" });
wywołuje praworodzajowyEquals
przeciążać. Problem dotyczy typów tablic. Załóżmy, że tak:
animals.Contains(new Animal { Name = "Fred" });
to dzwoninie rodzajowyEquals
metoda. Tak właściwieT[]
nie ujawniaICollection<T>.Contains
metoda. W powyższym przypadkuIEnumerable<Animal>.Contains
wywoływane jest przeciążenie rozszerzenia, które z kolei wywołujeICollection<T>.Contains
. Oto jakIEnumerable<T>.Contains
jest zaimplementowane:
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);
}
Moje pytania to:
CzemupowinienList<T>.Contains
iT[].Contains
zachowywać się inaczej? Innymi słowy, dlaczego poprzedni nazywa sięrodzajowyEquals
iostatni nie generycznyEquals
mimo że obie kolekcje są ogólne?Czy jest jakiś sposób, który mogę zobaczyćT[].Contains
realizacja?Edytować: Dlaczego to ma znaczenie lub dlaczego pytam o to:
Potyka się na wypadek, gdyby zapomniała nadpisaćnie rodzajowyEquals
podczas wdrażaniaIEquatable<T>
w takim przypadku nazywa się toT[].Contains
wykonuje kontrolę równości referencyjnej. Zwłaszcza, gdy oczekujewszystkie kolekcje ogólne działać dalejrodzajowyEquals
.
Tracisz wszystkie zalety wdrożeniaIEquatable<T>
(nawet jeśli nie jest to katastrofa dla typów referencyjnych).
Jak zauważono w komentarzach, po prostu chciałem poznać szczegóły wewnętrzne i wybory projektowe. Nie ma innej ogólnej sytuacji, o której mógłbym pomyśleć, gdzienie rodzajowyEquals
będzie preferowany, niezależnie od tegoList<T>
lub zestaw oparty (Dictionary<K,V>
itp.) operacje. Nawet gorzej,Czy Animal był strukturą, Animal []. Zawiera wywołaniarodzajowyEquals
, wszystko to sprawia, że implementacja T [] jest trochę dziwna, coś, co deweloperzy powinni wiedzieć.
Uwaga: Ogólna wersjaEquals
jest wywoływany tylko wtedy, gdy klasanarzędziaIEquatable<T>
. Jeśli klasa się nie implementujeIEquatable<T>
, nietypowe przeciążenieEquals
jest wywoływany niezależnie od tego, czy jest wywoływany przezList<T>.Contains
lubT[].Contains
.