Implementación de IEquatable
Proporcione igualdad con seguridad de tipos mediante Equals.
Implementación de IEquatable es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.
¿Por qué IEquatable<T>?
IEquatable<T> proporciona un método Equals(T other) con tipado fuerte. Evita el boxing en los tipos de valor y las conversiones de tipo en los tipos de referencia, lo que hace que la igualdad sea más rápida y clara.
Implementación de la interfaz
Implemente IEquatable<T> y proporcione Equals(T other). También debe invalidar el object.Equals heredado y GetHashCode para mantener la coherencia en todas las formas de comparación.
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)));
}
}Evite el boxing en las estructuras
El método no genérico object.Equals(object) convierte en boxing el argumento de una estructura. El método tipado Equals(Point other) de IEquatable<T> recibe la estructura directamente, por lo que no se produce ninguna asignación.
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
}
}Las colecciones utilizan IEquatable<T>
List<T>.Contains, Dictionary y HashSet prefieren IEquatable<T>.Equals cuando está disponible. Implementarlo hace que estas operaciones sean eficientes y correctas para su tipo.
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)));
}
}Tipos de referencia e IEquatable<T>
Las clases también pueden implementar IEquatable<T>. El método Equals tipado evita una conversión de tipo, y usted gestiona explícitamente null para el parámetro de referencia.
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));
}
}Envíe object.Equals al método tipado
Un patrón claro consiste en escribir la comparación una sola vez en Equals(T) y hacer que object.Equals delegue en ella. Así se garantiza que ambos se comporten de forma idéntica.
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)));
}
}Compare varios campos
En los tipos con varios campos, compárelos todos en Equals. Dos instancias son iguales solo si coinciden todos los campos relevantes.
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)));
}
}Combínelo con operadores
Combine IEquatable<T> con == y != para que quienes utilicen el tipo puedan comparar con cualquiera de las dos sintaxis, respaldadas por la misma comparación tipada.
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));
}
}Los registros lo implementan automáticamente
Un record de C# genera automáticamente IEquatable<T>, Equals basado en valores y GetHashCode. Cuando solo necesita igualdad por valor, un registro evita escribir código repetitivo.
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);
}
}Cuándo implementarlo manualmente
Implemente IEquatable<T> manualmente cuando necesite reglas de igualdad personalizadas, como nombres que no distingan mayúsculas de minúsculas o ignorar determinados campos, que un registro no puede expresar directamente.
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")));
}
}Póngalo en práctica
Implemente IEquatable<T> para un tipo de referencia pequeño y haga que todas las formas de comprobar la igualdad pasen por el método tipado.
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)));
}
}Comprobación rápida
Recuerde la ventaja de IEquatable
Resumen
IEquatable<T> proporciona igualdad con seguridad de tipos.
- Proporciona
Equals(T other), lo que evita el boxing en las estructuras y las conversiones de tipo en las clases. - Las colecciones lo prefieren para realizar búsquedas correctas y eficientes.
- Haga que
object.Equalsy los operadores pasen por el método tipado. - Los registros lo implementan automáticamente; impleméntelo manualmente para reglas personalizadas.
Preguntas frecuentes
¿La lección «Implementación de IEquatable» es gratis?
Sí — el texto completo de «Implementación de IEquatable» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Implementación de IEquatable»?
Proporcione igualdad con seguridad de tipos mediante Equals. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C# Academy?
No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Implementación de IEquatable»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C# Academy?
Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Implementación de IEquatable
- Sobrescritura de GetHashCode
- Implementación de IComparable
- IComparer para ordenación personalizada