Vertailuoperaattorien ylikuormitus
Toteuttakaa operaattorit ==, != ja järjestämistä varten.
Vertailuoperaattorien ylikuormitus on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C# Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C# Academy-kurssilla on yhteensä 4 oppituntia.
Vertailuoperaattorit ja yhtäsuuruus
Kun ylikuormitatte operaattorin ==, teidän on ylikuormitettava myös !=. Lisäksi Equals- ja GetHashCode-metodit kannattaa korvata, jotta kaikki yhtäsuuruuden muodot pysyvät yhdenmukaisina. C# valvoo operaattoriparia käännösaikana.
Operaattorien == ja != ylikuormitus
Kääntäjä edellyttää, että == ja != määritellään yhdessä. Kumpikin palauttaa bool-arvon, joka ilmaisee, pidetäänkö operandeja yhtä suurina.
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));
}
}Korvatkaa aina myös Equals
Operaattorit ratkaistaan käännösaikana staattisen tyypin perusteella, mutta Equals on virtuaalinen ja kokoelmat käyttävät sitä. Korvatkaa Equals, jotta sanakirjat ja List.Contains ovat samaa mieltä operaattorin == kanssa.
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));
}
}GetHashCoden on vastattava yhtäsuuruutta
Jos kaksi arvoa ovat yhtä suuria, niiden on palautettava sama hajautuskoodi. Muussa tapauksessa hajautukseen perustuvat kokoelmat, kuten Dictionary ja HashSet, toimivat virheellisesti.
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)));
}
}Järjestysoperaattorit < ja >
Myös relaatio-operaattoreita voi ylikuormittaa. Kuten yhtäsuuruusoperaattorien tapauksessa, < ja > on määriteltävä yhdessä, samoin <= ja >=.
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));
}
}Viitetyyppien yhtäsuuruus
Luokissa arvojen yhtäsuuruus tarkoittaa kenttien, ei viitteiden, vertaamista. Käsitelkää null huolellisesti, jotta operaattori ei heitä poikkeusta.
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"));
}
}Yhdenmukaisuus eri muodoissa
Kaikkien yhtäsuuruuden tarkistustapojen on annettava sama tulos: ==, Equals ja hajautuskoodi. Toteuttakaa == Equals-metodin avulla (tai päinvastoin), jotta totuudelle on vain yksi lähde.
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)));
}
}Operaattorit ja Equals kokoelmissa
Listahaku käyttää Equals-metodia, ei operaattoria ==, koska se toimii object-viitteillä. Jos ylikuormitatte vain operaattorin == ja unohdatte Equals-metodin, hauissa käytetään viite-identiteettiä ja ne voivat epäonnistua.
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")));
}
}Kääntäjän varoitusten asianmukainen poistaminen
Equals- ja GetHashCode-metodien korvaaminen operaattorien yhteydessä ei ole vain hyvien tapojen mukaista. Kääntäjä antaa varoituksen, jos ylikuormitatte operaattorin == korvaamatta Equals-metodia. Kun teette molemmat, varoitus poistuu ja virheet estyvät.
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));
}
}Kaiken yhdistäminen
Hyvin toimiva yhtäsuuruutta tukeva tyyppi määrittelee operaattorit == ja !=, korvaa metodit Equals ja GetHashCode sekä ohjaa ne kaikki yhden vertailun kautta. Tämä on arvon kaltaisten tyyppien tavoiteltu toteutustapa.
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)]);
}
}Kokeilkaa itse
Toteuttakaa täysin yhdenmukainen yhtäsuuruutta tukeva rakenne ja varmistakaa, että se toimii samanaikaisesti sanakirjan avaimena ja operaattorin == kanssa.
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)]);
}
}Pikatarkistus
Palauttakaa mieleenne yhtäsuuruuden ylikuormittamista koskevat säännöt.
Kertaus
Vertailuoperaattorien ylikuormitus edellyttää yhdenmukaisuutta.
==ja!=on määriteltävä yhdessä, samoin</>.- Korvatkaa
EqualsjaGetHashCodeniin, että ne vastaavat operaattoria==. - Yhtä suurilla arvoilla on oltava sama hajautuskoodi.
- Ohjatkaa kaikki yhtäsuuruustarkistukset yhden vertailumetodin kautta, jotta toteutukset eivät ajaudu erilleen.
Opi C# tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 93
- Oppitunnit
- 346
Usein kysytyt kysymykset
Onko oppitunti ”Vertailuoperaattorien ylikuormitus” ilmainen?
Kyllä – oppitunnin ”Vertailuoperaattorien ylikuormitus” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C# Academy-kurssin, päivitä CoddyKit PROhon. C# Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Vertailuoperaattorien ylikuormitus”?
Toteuttakaa operaattorit ==, != ja järjestämistä varten. Harjoittelet C# Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni C# Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin C# Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.
Kuinka kauan ”Vertailuoperaattorien ylikuormitus”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä C# Academy-oppitunnilla?
Kyllä. Jokainen C# Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Aritmeettisten operaattorien ylikuormitus
- Vertailuoperaattorien ylikuormitus
- Käyttäjän määrittämät muunnokset
- Operaattorien ylikuormituksen parhaat käytännöt