0Pricing
C# Academy · Lezione

Implementazione di IEquatable

Fornisca un'uguaglianza indipendente dal tipo con Equals.

Implementazione di IEquatable è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.

Perché IEquatable<T>?

IEquatable<T> fornisce un metodo Equals(T other) fortemente tipizzato. Evita il boxing per i tipi valore e i cast per i tipi riferimento, rendendo l'uguaglianza più veloce e chiara.

Implementare l'interfaccia

Implementi IEquatable<T> e fornisca Equals(T other). Dovrebbe anche eseguire l'override di object.Equals e GetHashCode ereditati, per mantenere coerenti tutti i percorsi.

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)));
    }
}

Evitare il boxing per le struct

Il metodo non generico object.Equals(object) esegue il boxing dell'argomento struct. Il metodo tipizzato Equals(Point other) fornito da IEquatable<T> riceve direttamente la struct, quindi non viene effettuata alcuna allocazione.

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
    }
}

Le raccolte usano IEquatable<T>

List<T>.Contains, Dictionary e HashSet preferiscono IEquatable<T>.Equals quando disponibile. Implementarlo rende queste operazioni efficienti e corrette per il Suo 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)));
    }
}

Tipi riferimento e IEquatable<T>

Anche le classi possono implementare IEquatable<T>. Il metodo Equals tipizzato evita un cast e consente di gestire esplicitamente null per il parametro di tipo riferimento.

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));
    }
}

Instradare object.Equals attraverso il metodo tipizzato

Un modello pulito consiste nello scrivere il confronto una sola volta in Equals(T) e nel fare in modo che object.Equals deleghi a quel metodo. Questo garantisce che entrambi si comportino in modo identico.

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)));
    }
}

Confrontare più campi

Per i tipi con più campi, li confronti tutti in Equals. Due istanze sono uguali solo se tutti i campi rilevanti corrispondono.

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)));
    }
}

Abbinare gli operatori

Combini IEquatable<T> con == e !=, così gli utenti possono confrontare i valori con entrambe le sintassi, entrambe basate sullo stesso confronto tipizzato.

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));
    }
}

I record lo implementano automaticamente

Un record C# genera automaticamente IEquatable<T>, Equals basato sul valore e GetHashCode. Quando serve solo l'uguaglianza basata sul valore, un record evita codice ripetitivo.

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);
    }
}

Quando implementarlo manualmente

Implementi IEquatable<T> manualmente quando servono regole di uguaglianza personalizzate, come nomi senza distinzione tra maiuscole e minuscole o l'esclusione di determinati campi, che un record non può esprimere direttamente.

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")));
    }
}

Provi Lei

Implementi IEquatable<T> per un piccolo tipo riferimento e faccia passare ogni percorso di uguaglianza attraverso il metodo tipizzato.

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)));
    }
}

Verifica rapida

Ricordi il vantaggio di IEquatable.

Riepilogo

IEquatable<T> fornisce un'uguaglianza sicura rispetto al tipo.

  • Fornisce Equals(T other), evitando il boxing per le strutture e i cast per le classi.
  • Le raccolte lo preferiscono per ricerche corrette ed efficienti.
  • Faccia passare object.Equals e gli operatori attraverso il metodo tipizzato.
  • I record lo implementano automaticamente; lo implementi manualmente per regole personalizzate.

Domande Frequenti

La lezione «Implementazione di IEquatable» è gratuita?

Sì — il testo completo di «Implementazione di IEquatable» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.

Cosa imparerò in «Implementazione di IEquatable»?

Fornisca un'uguaglianza indipendente dal tipo con Equals. Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C# Academy?

Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Implementazione di IEquatable»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C# Academy?

Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Implementazione di IEquatable
  2. Override di GetHashCode
  3. Implementazione di IComparable
  4. IComparer per l'ordinamento personalizzato
← Torna a C# Academy