Implémenter IEquatable
Fournissez une égalité sûre du point de vue du type avec Equals.
Implémenter IEquatable est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.
Pourquoi IEquatable<T> ?
IEquatable<T> fournit une méthode Equals(T other) fortement typée. Elle évite le boxing pour les types valeur et les conversions de type pour les types référence, ce qui rend l'égalité à la fois plus rapide et plus claire.
Implémenter l'interface
Implémentez IEquatable<T> et fournissez Equals(T other). Vous devez également redéfinir le object.Equals hérité ainsi que GetHashCode afin de garder toutes les formes d'égalité cohérentes.
using System;
public struct Point : IEquatable<Point>
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public bool Equals(Point other) => X == other.X && Y == other.Y;
public override bool Equals(object obj) => obj is Point p && Equals(p);
public override int GetHashCode() => HashCode.Combine(X, Y);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Point(1, 2).Equals(new Point(1, 2)));
}
}Éviter le boxing pour les structures
La méthode non générique object.Equals(object) applique le boxing à un argument de type structure. La méthode typée Equals(Point other) de IEquatable<T> reçoit directement la structure, ce qui évite toute allocation.
using System;
public struct Point : IEquatable<Point>
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public bool Equals(Point other) => X == other.X && Y == other.Y; // no boxing
public override bool Equals(object obj) => obj is Point p && Equals(p);
public override int GetHashCode() => HashCode.Combine(X, Y);
}
public class Program
{
public static void Main()
{
Point a = new Point(3, 4);
Point b = new Point(3, 4);
Console.WriteLine(a.Equals(b)); // calls the typed overload
}
}Les collections utilisent IEquatable<T>
List<T>.Contains, Dictionary et HashSet privilégient IEquatable<T>.Equals lorsqu'il est disponible. Son implémentation rend ces opérations efficaces et correctes pour votre type.
using System;
using System.Collections.Generic;
public struct Point : IEquatable<Point>
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public bool Equals(Point other) => X == other.X && Y == other.Y;
public override bool Equals(object obj) => obj is Point p && Equals(p);
public override int GetHashCode() => HashCode.Combine(X, Y);
}
public class Program
{
public static void Main()
{
var list = new List<Point> { new Point(0, 0), new Point(1, 1) };
Console.WriteLine(list.Contains(new Point(1, 1)));
}
}Types référence et IEquatable<T>
Les classes peuvent également implémenter IEquatable<T>. La méthode Equals typée évite une conversion de type, et vous gérez explicitement null pour le paramètre de type référence.
using System;
public class Person : IEquatable<Person>
{
public string Name;
public Person(string name) { Name = name; }
public bool Equals(Person other) => other != null && other.Name == Name;
public override bool Equals(object obj) => Equals(obj as Person);
public override int GetHashCode() => Name?.GetHashCode() ?? 0;
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Person("Ada").Equals(new Person("Ada")));
Console.WriteLine(new Person("Ada").Equals((Person)null));
}
}Faire passer object.Equals par la méthode typée
Une approche claire consiste à écrire la comparaison une seule fois dans Equals(T) et à faire déléguer object.Equals à cette méthode. Cela garantit que les deux méthodes se comportent de manière identique.
using System;
public struct Id : IEquatable<Id>
{
public int Value;
public Id(int value) { Value = value; }
public bool Equals(Id other) => Value == other.Value;
public override bool Equals(object obj) => obj is Id other && Equals(other);
public override int GetHashCode() => Value;
}
public class Program
{
public static void Main()
{
object boxed = new Id(5);
Console.WriteLine(boxed.Equals(new Id(5)));
}
}Comparer plusieurs champs
Pour les types comportant plusieurs champs, comparez-les tous dans Equals. Deux instances sont égales uniquement si chaque champ pertinent correspond.
using System;
public struct DateRange : IEquatable<DateRange>
{
public int Start, End;
public DateRange(int start, int end) { Start = start; End = end; }
public bool Equals(DateRange other) => Start == other.Start && End == other.End;
public override bool Equals(object obj) => obj is DateRange d && Equals(d);
public override int GetHashCode() => HashCode.Combine(Start, End);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new DateRange(1, 5).Equals(new DateRange(1, 5)));
Console.WriteLine(new DateRange(1, 5).Equals(new DateRange(1, 6)));
}
}Associer les opérateurs
Associez IEquatable<T> à == et != afin que les utilisateurs puissent comparer avec l'une ou l'autre syntaxe, toutes deux reposant sur la même comparaison typée.
using System;
public struct Money : IEquatable<Money>
{
public decimal Amount;
public Money(decimal a) { Amount = a; }
public bool Equals(Money other) => Amount == other.Amount;
public override bool Equals(object obj) => obj is Money m && Equals(m);
public override int GetHashCode() => Amount.GetHashCode();
public static bool operator ==(Money a, Money b) => a.Equals(b);
public static bool operator !=(Money a, Money b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Money(9.99m) == new Money(9.99m));
}
}Les enregistrements l'implémentent automatiquement
Un enregistrement C# record génère pour vous IEquatable<T>, une méthode Equals fondée sur les valeurs et GetHashCode. Lorsque l'égalité par valeur est tout ce dont vous avez besoin, un enregistrement évite le code répétitif.
using System;
public record Point(int X, int Y);
public class Program
{
public static void Main()
{
var a = new Point(1, 2);
var b = new Point(1, 2);
Console.WriteLine(a.Equals(b));
Console.WriteLine(a == b);
}
}Quand l'implémenter manuellement
Implémentez IEquatable<T> manuellement lorsque vous avez besoin de règles d'égalité personnalisées, comme des noms insensibles à la casse ou l'ignorance de certains champs, qu'un enregistrement ne peut pas exprimer directement.
using System;
public class CaseInsensitiveTag : IEquatable<CaseInsensitiveTag>
{
public string Name;
public CaseInsensitiveTag(string name) { Name = name; }
public bool Equals(CaseInsensitiveTag other)
=> other != null && string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
public override bool Equals(object obj) => Equals(obj as CaseInsensitiveTag);
public override int GetHashCode() => Name?.ToLowerInvariant().GetHashCode() ?? 0;
}
public class Program
{
public static void Main()
{
Console.WriteLine(new CaseInsensitiveTag("Red").Equals(new CaseInsensitiveTag("RED")));
}
}Essayez vous-même
Implémentez IEquatable<T> pour un petit type référence et faites passer toutes les formes d'égalité par la méthode typée.
using System;
using System.Collections.Generic;
public class Coordinate : IEquatable<Coordinate>
{
public int Lat, Lng;
public Coordinate(int lat, int lng) { Lat = lat; Lng = lng; }
public bool Equals(Coordinate other) => other != null && other.Lat == Lat && other.Lng == Lng;
public override bool Equals(object obj) => Equals(obj as Coordinate);
public override int GetHashCode() => HashCode.Combine(Lat, Lng);
}
public class Program
{
public static void Main()
{
var set = new HashSet<Coordinate> { new Coordinate(10, 20) };
Console.WriteLine(set.Contains(new Coordinate(10, 20)));
}
}Vérification rapide
Rappelez-vous l'avantage de IEquatable
Récapitulatif
IEquatable<T> fournit une égalité sûre du point de vue du type.
- Fournit
Equals(T other), en évitant le boxing pour les structures et les conversions de type pour les classes. - Les collections le privilégient pour des recherches correctes et efficaces.
- Faites passer
object.Equalset les opérateurs par la méthode typée. - Les enregistrements l'implémentent automatiquement ; implémentez-le manuellement pour des règles personnalisées.
Questions Fréquemment Posées
La leçon « Implémenter IEquatable » est-elle gratuite ?
Oui — le texte complet de « Implémenter IEquatable » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Implémenter IEquatable » ?
Fournissez une égalité sûre du point de vue du type avec Equals. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C# Academy ?
Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « Implémenter IEquatable » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?
Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Implémenter IEquatable
- Remplacer GetHashCode
- Implémenter IComparable
- IComparer pour un tri personnalisé