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>.Containsjest 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:

Czemupowinien List<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.

questionAnswers(3)

yourAnswerToTheQuestion