Chcę, aby moja Food
klasa mogła testować, ilekroć jest ona równa innej instancji Food
. Później użyję go na liście i chcę użyć jego List.Contains()
metody. Czy powinienem zaimplementować IEquatable<Food>
czy po prostu zastąpić Object.Equals()
? Z MSDN:
Ta metoda określa równość za pomocą domyślnego modułu porównującego równość zdefiniowanego przez obiektową implementację metody IEquatable.Equals dla T (typ wartości na liście).
Moje następne pytanie brzmi: z jakich funkcji / klas środowiska .NET korzystają Object.Equals()
? Czy powinienem go używać?
Odpowiedzi:
Głównym powodem jest wydajność. Kiedy leki generyczne zostały wprowadzone w .NET 2.0 były one w stanie dodać kilka zgrabnych klas takich jak
List<T>
,Dictionary<K,V>
,HashSet<T>
, itd. Struktury te w ogromnym stopniu korzystają zGetHashCode
iEquals
. Ale dla typów wartości wymagało to boksowania.IEquatable<T>
pozwala strukturze wdrożyć silnie typowanąEquals
metodę, więc nie jest wymagane boksowanie. Dzięki temu znacznie lepsza wydajność przy użyciu typów wartości z kolekcjami ogólnymi.Typy referencyjne nie odnoszą tak dużych korzyści, ale
IEquatable<T>
implementacja pozwala uniknąć rzutowania, zSystem.Object
którego może mieć znaczenie, jeśli jest często wywoływany.Jak zauważono na blogu Jareda Parsona , nadal musisz zaimplementować przesłonięcia obiektów.
źródło
IEquatable<T>
interfejs robi coś więcej niż przypomina programistom o dołączeniupublic bool Equals(T other)
członka do klasy lub struktury? Obecność lub brak interfejsu nie ma znaczenia w czasie wykonywania. Wydaje się, że przeciążenieEquals
jest wszystkim, co jest konieczne.Według MSDN :
Wygląda więc na to, że nie ma żadnej rzeczywistej różnicy funkcjonalnej między tymi dwoma, z wyjątkiem tego, że można je wywołać w zależności od sposobu użycia klasy. Z punktu widzenia wydajności lepiej jest używać wersji ogólnej, ponieważ nie wiąże się z nią kara za boksowanie / rozpakowywanie.
Z logicznego punktu widzenia lepiej jest również wdrożyć interfejs. Przesłonięcie obiektu tak naprawdę nikomu nie mówi, że twoja klasa jest rzeczywiście dająca się porównać. Zastąpienie może być po prostu klasą nic nie rób lub płytką implementacją. Korzystanie z interfejsu wyraźnie mówi: „Hej, ta rzecz jest ważna do sprawdzania równości!” To po prostu lepszy projekt.
źródło
Rozszerzając to, co powiedział Josh, o praktyczny przykład. +1 do Josha - miałem już napisać to samo w mojej odpowiedzi.
W ten sposób mam do ponownego użycia metodę Equals (), która działa od razu dla wszystkich moich klas pochodnych.
źródło
Jeśli zadzwonimy
object.Equals
, wymusza to kosztowne boksowanie według rodzajów wartości. Jest to niepożądane w scenariuszach wrażliwych na wydajność. Rozwiązaniem jest użyćIEquatable<T>
.Chodzi o
IEquatable<T>
to, że daje ten sam wynik,object.Equals
ale szybciej. Ograniczeniawhere T : IEquatable<T>
należy używać z typami ogólnymi, takimi jak poniżej.w przeciwnym razie wiąże się z
slower object.Equals()
.źródło