Operaattorien ylikuormituksen parhaat käytännöt
Pitäkää ylikuormitetut operaattorit intuitiivisina.
Operaattorien ylikuormituksen parhaat käytännöt on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/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.
Operaattorien ylikuormituksen parhaat käytännöt
Operaattorien ylikuormitus on tehokas työkalu. Hyvin käytettynä se tekee arvotyypeistä intuitiivisia, mutta huonosti käytettynä koodista vaikeaselkoista. Tässä oppitunnissa käsitellään periaatteita, joiden avulla ylikuormitetut operaattorit pysyvät ennakoitavina.
Ylikuormita vain, kun merkitys on ilmeinen
Ylikuormita operaattori vain, kun sen merkitys on tyypillesi yksiselitteinen. + vektorille tarkoittaa selvästi komponenttikohtaista yhteenlaskua, mutta + Order-tyypille vain hämmentäisi lukijoita.
using System;
public struct Vector2
{
public int X, Y;
public Vector2(int x, int y) { X = x; Y = y; }
// + means adding components: obvious and expected
public static Vector2 operator +(Vector2 a, Vector2 b)
=> new Vector2(a.X + b.X, a.Y + b.Y);
public override string ToString() => "(" + X + ", " + Y + ")";
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Vector2(1, 2) + new Vector2(3, 4));
}
}Säilytä matemaattiset odotukset
Pidä operaattorien toiminta intuition mukaisena: a + b pitäisi olla sama kuin b + a, kun matematiikka on kommutatiivista, eikä + saa salaa tehdä vähennyslaskua. Tällaiset yllätykset aiheuttavat vaikeasti havaittavia virheitä.
using System;
public struct Money
{
public decimal Amount;
public Money(decimal a) { Amount = a; }
public static Money operator +(Money a, Money b) => new Money(a.Amount + b.Amount);
public override string ToString() => "$" + Amount;
}
public class Program
{
public static void Main()
{
var x = new Money(3);
var y = new Money(5);
Console.WriteLine((x + y).Amount == (y + x).Amount); // commutative
}
}Pidä symmetria ja parit
Kieli yhdistää tietyt operaattorit pareiksi, mutta sinun kannattaa säilyttää myös looginen symmetria: jos lisäät +-operaattorin, harkitse myös --operaattoria; jos lisäät <-operaattorin, tarjoa myös >-operaattori ja vastaavat yhtäsuuruusversiot. Puolivalmiit operaattorijoukot turhauttavat käyttäjiä.
using System;
public struct Length
{
public int Mm;
public Length(int mm) { Mm = mm; }
public static Length operator +(Length a, Length b) => new Length(a.Mm + b.Mm);
public static Length operator -(Length a, Length b) => new Length(a.Mm - b.Mm);
public override string ToString() => Mm + "mm";
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Length(50) + new Length(20));
Console.WriteLine(new Length(50) - new Length(20));
}
}Älä muuta operandeja
Operaattorien pitäisi olla puhtaita: niiden tulee laskea ja palauttaa uusi arvo jättäen operandit ennalleen. Operandin muuttaminen +-operaattorin sisällä rikkoo kaikki lukijan odotukset.
using System;
public struct Vector2
{
public int X, Y;
public Vector2(int x, int y) { X = x; Y = y; }
public static Vector2 operator +(Vector2 a, Vector2 b)
=> new Vector2(a.X + b.X, a.Y + b.Y); // returns new, mutates nothing
public override string ToString() => "(" + X + ", " + Y + ")";
}
public class Program
{
public static void Main()
{
var a = new Vector2(1, 1);
var unused = a + new Vector2(9, 9);
Console.WriteLine("a is still " + a);
}
}Pidä == yhdenmukaisena Equalsin kanssa
Toistuva parhaiden käytäntöjen periaate on tämä: kun ylikuormitat ==-operaattorin, korvaa myös Equals ja GetHashCode, jotta kaikki yhtäsuuruuden tarkistusreitit toimivat samalla tavalla. Epäjohdonmukaisuus on yksi yleisimmistä operaattorivirheistä.
using System;
public struct Point
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public override bool Equals(object obj) => obj is Point p && p.X == X && p.Y == Y;
public override int GetHashCode() => HashCode.Combine(X, Y);
public static bool operator ==(Point a, Point b) => a.Equals(b);
public static bool operator !=(Point a, Point b) => !a.Equals(b);
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Point(1, 1) == new Point(1, 1));
}
}Tarjoa nimettyjä vaihtoehtoja
Jotkin kielet ja analyysityökalut eivät voi käyttää operaattoreita. Nimetyn metodin, kuten Add-metodin, tarjoaminen +-operaattorin rinnalla parantaa yhteentoimivuutta ja löydettävyyttä.
using System;
public struct Vector2
{
public int X, Y;
public Vector2(int x, int y) { X = x; Y = y; }
public Vector2 Add(Vector2 other) => new Vector2(X + other.X, Y + other.Y);
public static Vector2 operator +(Vector2 a, Vector2 b) => a.Add(b);
public override string ToString() => "(" + X + ", " + Y + ")";
}
public class Program
{
public static void Main()
{
var v = new Vector2(1, 2);
Console.WriteLine(v.Add(new Vector2(3, 4)));
Console.WriteLine(v + new Vector2(3, 4));
}
}Suosi operaattoreita arvon kaltaisissa tyypeissä
Operaattorit tuntuvat luontevilta muuttumattomissa, arvon kaltaisissa tyypeissä, kuten struct-tyypeissä tai record-tyyppisissä luokissa. Muuttuvissa, identiteettikeskeisissä tyypeissä nimetyt metodit yleensä ilmaisevat tarkoituksen paremmin.
using System;
public readonly struct Rational
{
public readonly int Num, Den;
public Rational(int n, int d) { Num = n; Den = d; }
public static Rational operator *(Rational a, Rational b)
=> new Rational(a.Num * b.Num, a.Den * b.Den);
public override string ToString() => Num + "/" + Den;
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Rational(1, 2) * new Rational(2, 3));
}
}Dokumentoi reunatapaukset
Kerro selkeästi, miten operaattorit käsittelevät erityistapauksia, kuten nollalla jakamista, luokkien null-operandeja tai ylivuotoa. Ennakoitava käsittely estää kutsujia joutumasta yllätetyiksi.
using System;
public struct SafeDiv
{
public int Value;
public SafeDiv(int v) { Value = v; }
// Documented behavior: dividing by zero yields zero
public static SafeDiv operator /(SafeDiv a, SafeDiv b)
=> new SafeDiv(b.Value == 0 ? 0 : a.Value / b.Value);
public override string ToString() => Value.ToString();
}
public class Program
{
public static void Main()
{
Console.WriteLine(new SafeDiv(10) / new SafeDiv(0));
Console.WriteLine(new SafeDiv(10) / new SafeDiv(2));
}
}Harkittu operaattorijoukko
Viimeistelty numeerinen tyyppi yhdistää muutaman intuitiivisen operaattorin, yhdenmukaisen yhtäsuuruuden käsittelyn ja muuttumattomuuden. Tulos toimii sisäänrakennetun luvun tavoin ja sitä on miellyttävä käyttää.
using System;
public readonly struct Vec
{
public readonly double X, Y;
public Vec(double x, double y) { X = x; Y = y; }
public static Vec operator +(Vec a, Vec b) => new Vec(a.X + b.X, a.Y + b.Y);
public static Vec operator -(Vec a, Vec b) => new Vec(a.X - b.X, a.Y - b.Y);
public static Vec operator *(Vec a, double k) => new Vec(a.X * k, a.Y * k);
public override string ToString() => "(" + X + ", " + Y + ")";
}
public class Program
{
public static void Main()
{
Console.WriteLine((new Vec(1, 2) + new Vec(3, 4)) * 2);
}
}Kokeile itse
Yhdistä käytännöt: määrittele muuttumaton arvotyyppi, intuitiiviset operaattorit, nimetty vaihtoehto ja yhdenmukainen yhtäsuuruuden käsittely.
using System;
public readonly struct Meters : IEquatable<Meters>
{
public readonly double Value;
public Meters(double v) { Value = v; }
public Meters Add(Meters other) => new Meters(Value + other.Value);
public static Meters operator +(Meters a, Meters b) => a.Add(b);
public bool Equals(Meters other) => Value == other.Value;
public override bool Equals(object obj) => obj is Meters m && Equals(m);
public override int GetHashCode() => Value.GetHashCode();
public static bool operator ==(Meters a, Meters b) => a.Equals(b);
public static bool operator !=(Meters a, Meters b) => !a.Equals(b);
public override string ToString() => Value + "m";
}
public class Program
{
public static void Main()
{
Console.WriteLine(new Meters(3) + new Meters(4));
Console.WriteLine(new Meters(7) == new Meters(7));
}
}Pikatarkistus
Sovella operaattorien parhaita käytäntöjä.
Kertaus
Hyvä operaattorien ylikuormitus on harkittua ja ennakoitavaa.
- Ylikuormita vain, kun merkitys on ilmeinen.
- Säilytä matemaattiset odotukset ja symmetria.
- Pidä operaattorit puhtaina: palauta uusia arvoja äläkä koskaan muuta operandeja.
- Pidä
==yhdenmukaisenaEquals/GetHashCode-toteutusten kanssa. - Tarjoa nimettyjä vaihtoehtoja ja suosi arvon kaltaisia tyyppejä.
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 ”Operaattorien ylikuormituksen parhaat käytännöt” ilmainen?
Kyllä – oppitunnin ”Operaattorien ylikuormituksen parhaat käytännöt” 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 ”Operaattorien ylikuormituksen parhaat käytännöt”?
Pitäkää ylikuormitetut operaattorit intuitiivisina. 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 4/4.
Kuinka kauan ”Operaattorien ylikuormituksen parhaat käytännöt”-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