C# Academy · Lektion

Implementera IEquatable

Tillhandahåll typsäker likhet med Equals.

Lektion 1 av 413 steg

Implementera IEquatable är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för C# Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i C# Academy innehåller totalt 4 lektioner.

Varför IEquatable<T>?

IEquatable<T> tillhandahåller en starkt typad metod, Equals(T other). Den undviker boxing för värdetyper och castning för referenstyper, vilket gör likhetsjämförelser både snabbare och tydligare.

Implementera gränssnittet

Implementera IEquatable<T> och tillhandahåll Equals(T other). Du bör också åsidosätta det ärvda object.Equals och GetHashCode så att alla vägar förblir konsekventa.

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

Undvik boxing för strukturer

Den icke-generiska object.Equals(object) boxar ett strukturargument. Den typade Equals(Point other) från IEquatable<T> tar emot strukturen direkt, så ingen allokering sker.

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

Samlingar använder IEquatable<T>

List<T>.Contains, Dictionary och HashSet föredrar IEquatable<T>.Equals när det finns tillgängligt. Genom att implementera det blir dessa operationer effektiva och korrekta för din typ.

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

Referenstyper och IEquatable<T>

Klasser kan också implementera IEquatable<T>. Den typade Equals-metoden undviker en cast, och du hanterar null explicit för referensparametern.

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

Låt object.Equals använda den typade metoden

Ett tydligt mönster är att skriva jämförelsen en gång i Equals(T) och låta object.Equals delegera till den. Då garanteras att båda fungerar identiskt.

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

Jämför flera fält

För typer med flera fält ska du jämföra alla fält i Equals. Två instanser är lika endast om alla relevanta fält överensstämmer.

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

Kombinera med operatorer

Kombinera IEquatable<T> med == och != så att användarna kan jämföra med båda skrivsätten, där båda bygger på samma typade jämförelse.

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

Records implementerar det automatiskt

Ett C# record genererar IEquatable<T>, värdebaserad Equals och GetHashCode åt dig. När värdebaserad likhet är allt du behöver sparar ett record mycket standardkod.

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

När du bör implementera manuellt

Implementera IEquatable<T> för hand när du behöver egna likhetsregler, till exempel skiftlägesokänsliga namn eller att vissa fält ska ignoreras, som ett record inte kan uttrycka direkt.

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

Prova själv

Implementera IEquatable<T> för en liten referenstyp och låt alla vägar för likhetsjämförelse gå via den typade metoden.

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

Snabb kontroll

Påminn dig om fördelen med IEquatable.

Sammanfattning

IEquatable<T> ger typsäker likhetsjämförelse.

  • Tillhandahåller Equals(T other) och undviker boxing för strukturer och castning för klasser.
  • Samlingar föredrar det för korrekta och effektiva uppslagningar.
  • Låt object.Equals och operatorerna använda den typade metoden.
  • Records implementerar det automatiskt; implementera det manuellt för egna regler.
Gratis att börja

Lär dig C# med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
93
Lektioner
346

Vanliga frågor

Är lektionen ”Implementera IEquatable” gratis?

Ja – hela texten till ”Implementera IEquatable” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i C# Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i C# Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Implementera IEquatable”?

Tillhandahåll typsäker likhet med Equals. Ni övar på C# Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig C# Academy?

Du behöver inga förkunskaper. Utbildningen i C# Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Implementera IEquatable”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här C# Academy-lektionen?

Ja. Varje C# Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Implementera IEquatable
  2. Åsidosätta GetHashCode
  3. Implementera IComparable
  4. IComparer för anpassad sortering
← Tillbaka till C# Academy