Överlagra jämförelseoperatorer
Implementera ==, != och ordningsoperatorer.
Överlagra jämförelseoperatorer är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 2 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.
Jämförelseoperatorer och likhet
När ni överlagrar == måste ni även överlagra !=, och ni bör åsidosätta Equals och GetHashCode så att alla former av likhetsjämförelse förblir konsekventa. C# tvingar fram operatorparet vid kompilering.
Överlagra == och !=
Kompilatorn kräver att == och != definieras tillsammans. Båda returnerar en bool som anger om operanderna anses vara lika.
using System;
public struct Point
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
public static bool operator !=(Point a, Point b) => !(a == b);
public override bool Equals(object obj) => obj is Point p && this == p;
public override int GetHashCode() => HashCode.Combine(X, Y);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Point(1, 2) == new Point(1, 2));
Console.WriteLine(new Point(1, 2) != new Point(3, 4));
}
}Åsidosätt alltid Equals också
Operatorer löses vid kompilering utifrån den statiska typen, men Equals är virtuell och används av samlingar. Åsidosätt Equals så att dictionaries och List.Contains överensstämmer med er ==.
using System;
public struct Point
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
public static bool operator !=(Point a, Point b) => !(a == b);
public override bool Equals(object obj) => obj is Point p && this == p;
public override int GetHashCode() => HashCode.Combine(X, Y);
}
public class Program
{
public static void Main()
{
object a = new Point(1, 2);
object b = new Point(1, 2);
Console.WriteLine(a.Equals(b));
}
}GetHashCode måste överensstämma med likhet
Om två värden är lika måste de returnera samma hashkod. Annars kommer hashbaserade samlingar som Dictionary och HashSet att fungera felaktigt.
using System;
using System.Collections.Generic;
public struct Point
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public static bool operator ==(Point a, Point b) => a.X == b.X && a.Y == b.Y;
public static bool operator !=(Point a, Point b) => !(a == b);
public override bool Equals(object obj) => obj is Point p && this == p;
public override int GetHashCode() => HashCode.Combine(X, Y);
}
public class Program
{
public static void Main()
{
var set = new HashSet<Point> { new Point(1, 2) };
Console.WriteLine(set.Contains(new Point(1, 2)));
}
}Ordningoperatorerna < och >
Ni kan även överlagra relationsoperatorerna. Precis som för likhet måste < och > definieras tillsammans, och likaså <= och >=.
using System;
public struct Weight
{
public int Grams;
public Weight(int g) { Grams = g; }
public static bool operator <(Weight a, Weight b) => a.Grams < b.Grams;
public static bool operator >(Weight a, Weight b) => a.Grams > b.Grams;
public override string ToString() => Grams + "g";
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Weight(100) < new Weight(200));
Console.WriteLine(new Weight(300) > new Weight(200));
}
}Likhet för referenstyper
För klasser innebär värdelikhet att fälten jämförs i stället för referenserna. Hantera null försiktigt så att operatorn inte kastar ett undantag.
using System;
public class Person
{
public string Name;
public Person(string name) { Name = name; }
public static bool operator ==(Person a, Person b)
{
if (ReferenceEquals(a, b)) return true;
if (a is null || b is null) return false;
return a.Name == b.Name;
}
public static bool operator !=(Person a, Person b) => !(a == b);
public override bool Equals(object obj) => this == (obj as Person);
public override int GetHashCode() => Name?.GetHashCode() ?? 0;
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Person("Ann") == new Person("Ann"));
}
}Konsekvens mellan alla former
Alla vägar för likhetsjämförelse bör ge samma resultat: ==, Equals och hashkoden. Implementera == med Equals (eller tvärtom) så att det finns en enda källa till sanningen.
using System;
public struct 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 static bool operator ==(Id a, Id b) => a.Equals(b);
public static bool operator !=(Id a, Id b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Id(7) == new Id(7));
Console.WriteLine(new Id(7).Equals(new Id(8)));
}
}Operatorer jämfört med Equals i samlingar
Sökning i List använder Equals, inte ==, eftersom den arbetar med object-referenser. Om ni bara överlagrar == och glömmer Equals används referensidentitet vid sökningar, som därför kan misslyckas.
using System;
using System.Collections.Generic;
public struct Tag
{
public string Name;
public Tag(string name) { Name = name; }
public override bool Equals(object obj) => obj is Tag t && t.Name == Name;
public override int GetHashCode() => Name?.GetHashCode() ?? 0;
public static bool operator ==(Tag a, Tag b) => a.Equals(b);
public static bool operator !=(Tag a, Tag b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
var list = new List<Tag> { new Tag("red"), new Tag("blue") };
Console.WriteLine(list.Contains(new Tag("blue")));
}
}Undertryck kompilatorvarningar korrekt
Att åsidosätta Equals och GetHashCode tillsammans med operatorerna är inte bara god sed; kompilatorn varnar om ni överlagrar == utan att åsidosätta Equals. Genom att göra båda delarna försvinner varningen och buggar förebyggs.
using System;
public struct Cell
{
public int Row, Col;
public Cell(int r, int c) { Row = r; Col = c; }
public override bool Equals(object obj) => obj is Cell c && c.Row == Row && c.Col == Col;
public override int GetHashCode() => HashCode.Combine(Row, Col);
public static bool operator ==(Cell a, Cell b) => a.Equals(b);
public static bool operator !=(Cell a, Cell b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Cell(0, 0) == new Cell(0, 0));
}
}Sätt ihop alla delar
En välfungerande likhetsjämförbar typ definierar == och !=, åsidosätter Equals och GetHashCode och låter alla använda samma jämförelse. Det är riktmärket för värdeliknande typer.
using System;
using System.Collections.Generic;
public struct Color
{
public int R, G, B;
public Color(int r, int g, int b) { R = r; G = g; B = b; }
public override bool Equals(object obj) => obj is Color c && c.R == R && c.G == G && c.B == B;
public override int GetHashCode() => HashCode.Combine(R, G, B);
public static bool operator ==(Color a, Color b) => a.Equals(b);
public static bool operator !=(Color a, Color b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
var dict = new Dictionary<Color, string> { [new Color(255, 0, 0)] = "red" };
Console.WriteLine(dict[new Color(255, 0, 0)]);
}
}Prova själv
Implementera en helt konsekvent likhetsjämförbar struct och kontrollera att den fungerar både som nyckel i en dictionary och med operatorn ==.
using System;
using System.Collections.Generic;
public struct GridPos
{
public int Row, Col;
public GridPos(int r, int c) { Row = r; Col = c; }
public override bool Equals(object obj) => obj is GridPos p && p.Row == Row && p.Col == Col;
public override int GetHashCode() => HashCode.Combine(Row, Col);
public static bool operator ==(GridPos a, GridPos b) => a.Equals(b);
public static bool operator !=(GridPos a, GridPos b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
var grid = new Dictionary<GridPos, string> { [new GridPos(1, 1)] = "player" };
Console.WriteLine(new GridPos(1, 1) == new GridPos(1, 1));
Console.WriteLine(grid[new GridPos(1, 1)]);
}
}Snabbtest
Repetera reglerna för att överlagra likhet.
Sammanfattning
Överlagring av jämförelseoperatorer kräver konsekvens.
==och!=måste definieras tillsammans, och likaså</>.- Åsidosätt
EqualsochGetHashCodeså att de överensstämmer med==. - Lika värden måste ha samma hashkod.
- Låt all likhetsjämförelse gå genom en enda jämförelsemetod för att undvika avvikelser.
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 ”Överlagra jämförelseoperatorer” gratis?
Ja – hela texten till ”Överlagra jämförelseoperatorer” 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 ”Överlagra jämförelseoperatorer”?
Implementera ==, != och ordningsoperatorer. 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 2 av 4.
Hur lång tid tar lektionen ”Överlagra jämförelseoperatorer”?
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
- Överlagra aritmetiska operatorer
- Överlagra jämförelseoperatorer
- Användardefinierade konverteringar
- God praxis för operatoröverlagring