C# - interfejsy IComparable oraz IComparable<>
W języku C#, istnieje możliwość porównywania zmiennych typu prostego (typu wartości), za pomocą operatorów ==, >, <, >= oraz <=. Twórcy języka C# doszli do wniosku, że warto dostarczyć podobny mechanizm dla typów referencyjnych, tworząc interfejsy IComparable<> oraz IComparable.
W ramach tych interfejsów dostarczono metodę CompareTo(), która:
- ma składnie:
public int CompareTo(T other) { /* ... */ }
- przyjmuje argument np. tego samego typu co klasa implementująca (chodzi o typ
T), - zwraca wynik:
+1lub wartość dodatnią
jeśli aktualny obiekt jest większy od obiektu
other
(czyli:this>other)-1lub wartość ujemną
jeśli aktualny obiekt jest mniejszy od obiektu
other
(czyli:this<other)0jeśli aktualny obiekt jest równy obiektowi
other
(czyli:this==other)
Uwaga:
Typy proste również posiadają dodatkowo dostarczone implementacje metod
CompareTo(), co sprawia, że wszystkie typy w C# są ujednolicone pod względem porównywania i mogą być używane zamiennie np. w typach generycznych.
Motywacja
Interfejsy IComparable<> oraz IComparable znajdują szerokie zastosowanie w:
- strukturach danych, gdy wymagane jest sprawdzanie, który obiekt jest większy od którego,
- funkcjach sortujacych dane,
- itp.
Praktyczny przykład
Poniżej, można znaleźć klasę Student, która implementuje IComparable<> - to programista decuduje, jak wygląda logika porównująca obiekty. Aby zobrazować działanie CompareTo() obiekty umieszczono w tablicy i posortowano po wieku studentów.
using System;
using System.Text;
public class Program
{
public static void Main()
{
Student[] students = new Student[]
{
new Student("Ewa", 21),
new Student("Jan", 25),
new Student("Tomasz", 18)
};
Console.WriteLine("Nie posortowane: ");
for (int i = 0; i < students.Length; ++i)
Console.WriteLine(students[i]);
Array.Sort(students); // podczas sortowania wykorzystana zostanie metoda CompareTo()
Console.WriteLine("Posortowane po wieku: ");
for (int i = 0; i < students.Length; ++i)
Console.WriteLine(students[i]);
}
}
public class Student: IComparable<Student>
{
private string name;
private int age;
public Student(string name, int age)
{
this.name = name;
this.age = age;
}
public int CompareTo(Student other)
{
if (other == null) return -1;
if (other == this) return 0;
int diff = this.age - other.age;
if (this.age > other.age) return +1;
if (this.age < other.age) return -1;
return 0; // gdy: this.age == other.age
}
public override string ToString()
{
return "Student: " + this.name + " " + this.age;
}
}
Wynik:
Nie posortowane:
Student: Ewa 21
Student: Jan 25
Student: Tomasz 18
Posortowane po wieku:
Student: Tomasz 18
Student: Ewa 21
Student: Jan 25