C# Academy · Lektion

God praxis för operatoröverlagring

Håll överlagrade operatorer intuitiva.

Lektion 4 av 413 steg

God praxis för operatoröverlagring är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 4 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.

Bästa praxis för operatoröverlagring

Operatoröverlagring är ett kraftfullt verktyg. Rätt använd gör den värdetyper intuitiva, men fel använd gör koden svårbegriplig. Den här lektionen går igenom principer som gör överlagrade operatorer förutsägbara.

Överlagra endast när betydelsen är uppenbar

Överlagra en operator endast när dess betydelse är entydig för din typ. + på en vektor betyder tydligt addition komponent för komponent, medan + på en Order bara skulle förvirra läsarna.

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

Bevara matematiska förväntningar

Håll operatorerna i linje med intuitionen: a + b bör vara lika med b + a när matematiken är kommutativ, och + bör inte i hemlighet utföra subtraktion. Överraskningar här orsakar svårupptäckta buggar.

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

Bevara symmetri och parbildning

Språket kopplar ihop vissa operatorer, men du bör också upprätthålla logisk symmetri: om du lägger till +, bör du överväga -; om du lägger till <, bör du också tillhandahålla > och motsvarande varianter med likhetstecken. Halvfärdiga operatoruppsättningar frustrerar användarna.

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

Ändra inte operanderna

Operatorer bör vara rena: beräkna och returnera ett nytt värde utan att ändra operanderna. Att ändra en operand inuti + bryter mot alla förväntningar en läsare har.

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

Håll == konsekvent med Equals

En återkommande rekommendation är att alltid åsidosätta Equals och GetHashCode när du överlagrar ==, så att alla vägar för likhetsjämförelse ger samma resultat. Inkonsekvens här är en av de vanligaste operatorbuggarna.

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

Tillhandahåll namngivna alternativ

Vissa språk och analysverktyg kan inte använda operatorer. Om du erbjuder en namngiven metod som Add tillsammans med + förbättras interoperabiliteten och upptäckbarheten.

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

Föredra operatorer på värdeliknande typer

Operatorer känns naturliga för oföränderliga, värdeliknande typer (strukturer eller record-liknande klasser). För föränderliga typer där identiteten är viktig kommunicerar namngivna metoder oftast avsikten bättre.

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

Dokumentera specialfall

Var tydlig med hur operatorer hanterar specialvärden: division med noll, null-operander för klasser eller spill. Förutsägbar hantering förhindrar att anroparna blir tagna på sängen.

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

En genomtänkt operatoruppsättning

En välutformad numerisk typ kombinerar några intuitiva operatorer, konsekvent likhet och oföränderlighet. Resultatet fungerar som ett inbyggt tal och är behagligt att använda.

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

Prova själv

Samla principerna: en oföränderlig värdetyp, intuitiva operatorer, ett namngivet alternativ och konsekvent likhet.

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

Snabb kontroll

Tillämpa bästa praxis för operatorer.

Sammanfattning

Bra operatoröverlagring är genomtänkt och förutsägbar.

  • Överlagra endast när betydelsen är uppenbar.
  • Bevara matematiska förväntningar och symmetri.
  • Håll operatorerna rena: returnera nya värden och ändra aldrig operanderna.
  • Håll == konsekvent med Equals/GetHashCode.
  • Erbjud namngivna alternativ och föredra värdeliknande typer.
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 ”God praxis för operatoröverlagring” gratis?

Ja – hela texten till ”God praxis för operatoröverlagring” 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 ”God praxis för operatoröverlagring”?

Håll överlagrade operatorer intuitiva. 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 4 av 4.

Hur lång tid tar lektionen ”God praxis för operatoröverlagring”?

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. Överlagra aritmetiska operatorer
  2. Överlagra jämförelseoperatorer
  3. Användardefinierade konverteringar
  4. God praxis för operatoröverlagring
← Tillbaka till C# Academy