Operatoröverlagring – fördefinierade unary-, aritmetiska, likhets- och jämförelseoperatorer

En användardefinierad typ kan överbelasta en fördefinierad C#-operator. En typ kan alltså tillhandahålla anpassad implementering av en åtgärd om en eller båda operanderna är av den typen. Avsnittet Överbelastningsbara operatorer visar vilka C#-operatorer som kan överbelastas.

Använd nyckelordet operator för att deklarera en operator. En operatörsdeklaration måste uppfylla följande regler:

  • Den innehåller både en public och en static modifierare.
  • En unary-operator har en indataparameter. En binär operator har två indataparametrar. I varje fall måste minst en parameter ha typen T eller T? var T är den typ som innehåller operatordeklarationen.

I följande exempel definieras en förenklad struktur som representerar ett rationellt tal. Strukturen överbelastar några av de aritmetiska operatorerna:

public readonly struct Fraction
{
    private readonly int num;
    private readonly int den;

    public Fraction(int numerator, int denominator)
    {
        if (denominator == 0)
        {
            throw new ArgumentException("Denominator cannot be zero.", nameof(denominator));
        }
        num = numerator;
        den = denominator;
    }

    public static Fraction operator +(Fraction a) => a;
    public static Fraction operator -(Fraction a) => new Fraction(-a.num, a.den);

    public static Fraction operator +(Fraction a, Fraction b)
        => new Fraction(a.num * b.den + b.num * a.den, a.den * b.den);

    public static Fraction operator -(Fraction a, Fraction b)
        => a + (-b);

    public static Fraction operator *(Fraction a, Fraction b)
        => new Fraction(a.num * b.num, a.den * b.den);

    public static Fraction operator /(Fraction a, Fraction b)
    {
        if (b.num == 0)
        {
            throw new DivideByZeroException();
        }
        return new Fraction(a.num * b.den, a.den * b.num);
    }

    public override string ToString() => $"{num} / {den}";
}

public static class OperatorOverloading
{
    public static void Main()
    {
        var a = new Fraction(5, 4);
        var b = new Fraction(1, 2);
        Console.WriteLine(-a);   // output: -5 / 4
        Console.WriteLine(a + b);  // output: 14 / 8
        Console.WriteLine(a - b);  // output: 6 / 8
        Console.WriteLine(a * b);  // output: 5 / 8
        Console.WriteLine(a / b);  // output: 10 / 4
    }
}

Du kan utöka föregående exempel genom att definiera en implicit konvertering från int till Fraction. Sedan skulle överlagrade operatorer ha stöd för argument av dessa två typer. Det innebär att det skulle bli möjligt att lägga till ett heltal till ett bråk och få ett bråk som ett resultat.

Du använder också nyckelordet operator för att definiera en konvertering av anpassad typ. Mer information finns i Användardefinierade konverteringsoperatorer.

Överbelastningsbara operatorer

I följande tabell visas de operatorer som kan överbelastas:

Operatorer Kommentar
+x, -x, !x, ~x, ++, , --, , truefalse Operatorerna true och false måste vara överlagrade tillsammans.
x + y, x - y, x * y, x / y, , , x % y
x & y, x | y, , x ^ y
x << y, , x >> yx >>> y
x == y, x != y, x < y, x > y, , , x <= yx >= y Måste vara överlagrade i par enligt följande: == och !=, < och >, <= och >=.

Operatorer som inte kan överbelastas

I följande tabell visas de operatorer som inte kan överbelastas:

Operatorer Alternativ
x && y, x || y Överbelasta både operatorerna true och false operatorerna & eller | . Mer information finns i Användardefinierade villkorsstyrda logiska operatorer.
a[i], a?[i] Definiera en indexerare.
(T)x Definiera anpassade typkonverteringar som kan utföras av ett cast-uttryck. Mer information finns i Användardefinierade konverteringsoperatorer.
+=, -=, *=, /=, %=, &=, , |=, ^=, <<=, , , >>=>>>= Överbelasta motsvarande binära operator. När du till exempel överbelastar den binära + operatorn += är den implicit överbelastad.
^x, x = y, x.y, x?.y, c ? t : f, , x ?? y, , ??= y
x..y, x->y, =>, f(x), as, await, checked, unchecked, , default, delegate, is, nameof, , new
sizeof, stackalloc, switch, , , typeofwith
Inga.

Språkspecifikation för C#

Mer information finns i följande avsnitt i C#-språkspecifikationen:

Se även