C# - interfejsy IEquatable oraz IEquatable<>
W języku C#, istnieje możliwość porównywania zmiennych za pomocą operatora ==.
Gdy dokonujemy takiego porównania dla zmienncych:
- typu prostego (typu wartości), np.
byte,short,int,long,float,double,char, itp. następuje porównanie po wartości (czyli:1 == 1zwracaTrue, a2 == 4zwracaFalse), - typu referencyjnego, np.
Object, następuje porównanie po referencji.
Uwaga: Wyjątkiem są typy gdzie przeładowano operator
==, np.String, `może własna klasaStudent?`, itp. gdzie operator==zadziała poprawnie, ograniczając tym sposobem porównywanie referencji - coś za coś.
Twórcy języka C# doszli do wniosku, że warto dostarczyć ujednolicony mechanizm do porównywania obiektów po wartości, tworząc interfejsy IEquatable<> oraz IEquatable - poniżej zamieszczono praktyczny przykład.
Motywacja
Interfejsy IEquatable<> oraz IEquatable znajdują szerokie zastosowanie w strukturach danych, gdzie wymagane jest porównywanie obiektów po wartościach, np. w słownikach (klasa Dictionary<>), gdzie odwołujemy się po kluczach, którymi mogą też być obiekty.
Praktyczny przykład
Poniżej, można znaleźć klasę Student, która implementuje IEquatable<>.
using System;
using System.Text;
public class Program
{
public static void Main()
{
Student student1 = new Student("Jan", 25);
Student student2 = new Student("Jan", 25);
Student student3 = new Student("Tomasz", 18);
// Porównanie po referencjach:
Console.WriteLine(student1 == student2); // False
Console.WriteLine(student1 == student3); // False
Console.WriteLine(student1 == student1); // True
// Porównanie po wartościach:
Console.WriteLine(student1.Equals(student2)); // True
Console.WriteLine(student1.Equals(student3)); // False
Console.WriteLine(student1.Equals(null)); // False // wykonany scenariusz: if (other == null) return false;
Console.WriteLine(student1.Equals(student1)); // True // wykonany scenariusz: if (other == this) return true;
}
}
public class Student: IEquatable<Student>
{
private string name;
private int age;
public Student(string name, int age)
{
this.name = name;
this.age = age;
}
public bool Equals(Student other)
{
if (other == null) return false;
if (other == this) return true; // jeśli other i this wskazują na te same obiekty w pamięci - porównanie typów referencyjnych
return Object.Equals(this.name, other.name) && Object.Equals(this.age, other.age);
}
}