Główną różnicą pomiędzy IComparable i IComparable <> jest to, że najpierw jest wstępnie rodzajowych więc pozwala wywołać porównanie metody z dowolnego obiektu, natomiast drugi wymusza że podziela tego samego typu:
IComparable - CompareTo(object other);
IComparable<T> - CompareTo(T other);
Wybrałbym drugą opcję pod warunkiem, że nie zamierzasz używać żadnej starej biblioteki .net 1.0, gdzie typy nie mogą implementować nowoczesnego, ogólnego rozwiązania. Zyskasz wzrost wydajności, ponieważ unikniesz boksowania, a porównania nie będą musiały sprawdzać zgodności typów, a także uzyskasz ciepłe uczucie, które wynika z robienia rzeczy w najbardziej nowatorski sposób ...
Aby odpowiedzieć na bardzo dobry i trafny punkt Jeffa, argumentowałbym, że dobrą praktyką jest umieszczenie jak najmniejszej liczby ograniczeń na poziomie generycznym, jaki jest wymagany do wykonania zadania. Ponieważ masz pełną kontrolę nad kodem wewnątrz generic, wiesz, czy używasz metod wymagających podstawowego typu IComparable. Tak więc, biorąc swój komentarz pod uwagę Osobiście według poniższych zasad:
Jeżeli nie spodziewasz rodzajową użyć wszelkich typów, które tylko implementują IComparable (tj dziedzictwo kod 1.0) i nie wzywają dowolny metody z wnętrza generic, które opierają się na parametrze IComparable, a następnie użyj tylko ograniczenia IComparable <>.
Jeśli są użyciu typów, które tylko implementują IComparable następnie użyć tego ograniczenia tylko
Jeśli używasz metody, które wymagają IComparable parametr, ale nie przy użyciu typów, które tylko implementują IComparable następnie przy użyciu zarówno ograniczenia, jak w odpowiedzi Jeffa zwiększy wydajność, gdy użyjesz metod akceptujących typ ogólny.
Aby rozwinąć na trzecim reguły - załóżmy, że klasa piszesz jest następujący:
public class StrangeExample<T> where ... //to be decided
{
public void SortArray(T[] input)
{
Array.Sort(input);
}
public bool AreEqual(T a, T b)
{
return a.CompareTo(b) == 0;
}
}
I musimy zdecydować, jakie ograniczenia, aby umieścić na nim. Metoda SortArray wywołuje metodę Array.Sort, która wymaga przekazania tablicy, która zawiera obiekty implementujące funkcję IComparable. Dlatego koniecznością mieć IComparable ograniczenia:
public class StrangeExample<T> where T : IComparable
Teraz klasa będzie działać poprawnie skompilować i jak tablica T jest ważny dla Array.sort i jest ważna metoda .CompareTo zdefiniowane w interfejsie. Jednakże, jeśli jesteś pewien, że nie będzie chciał korzystać z klasy z typem, który nie również wdrożenia IComparable <> Interfejs można przedłużyć ograniczenia do:
public class StrangeExample<T> where T : IComparable, IComparable<T>
To oznacza, że gdy AreEqual nazywa go wykorzysta szybszą, ogólną metodę CompareTo, a zobaczysz korzyści związane z wydajnością kosztem braku możliwości użycia go ze starymi typami .NET 1.0. Z drugiej strony, jeśli nie masz metody AreEqual, to nie ma żadnej przewagi w stosunku do wiązania IComparable <>, więc równie dobrze możesz go upuścić - i tak korzystasz tylko z implementacji IComparable.
Bruno: w twoim kodzie, wolałbym delegować zadanie porównania w CompareTo (obiekt) do CompareTo (MyType) w drugiej gałęzi CompareTo (obiekt), zamiast powielać kod. – Steve