Operatorüberladung – vordefinierte unäre und arithmetische sowie Gleichheits- und Vergleichsoperatoren

Ein benutzerdefinierter Typ kann einen vordefinierten C#-Operator überladen. Das bedeutet, dass ein Typ die benutzerdefinierte Implementierung eines Vorgangs bereitstellen kann, wenn mindestens einer der beiden Operanden vom selben Typ ist. Im Abschnitt Überladbare Operatoren werden die C#-Operatoren angegeben, die überladen werden können.

Verwenden Sie das Schlüsselwort operator, um einen Operator zu deklarieren. Jede Operatordeklaration muss mit den folgenden Regeln konform sein:

  • Sie enthält sowohl einen public- als auch einen static-Modifizierer.
  • Ein unärer Operator verfügt über einen Eingabeparameter. Ein binärer Operator verfügt über zwei Eingabeparameter. Auf jeden Fall muss mindestens ein Parameter vom Typ T oder T? sein, wobei T der Typ ist, der die Operatordeklaration enthält.

Das folgende Beispiel definiert eine vereinfachte Struktur für die Darstellung einer rationalen Zahl. Die Struktur überlädt einige der arithmetischen Operatoren:

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

Sie könnten das vorherige Beispiel erweitern, indem Sie eine implizite Konvertierung von int nach Fraction definieren. Dann würden überladene Operatoren Argumente dieser beiden Typen unterstützen. Das bedeutet, dass es dann möglich wäre, eine ganze Zahl und einen Bruch zu addieren und als Ergebnis einen Bruch zu erhalten.

Verwenden Sie zudem das Kennwort operator, um eine benutzerdefinierte Konvertierung zu definieren. Weitere Informationen finden Sie unter Benutzerdefinierte Konvertierungsoperatoren.

Überladbare Operatoren

Die folgende Tabelle zeigt die Operatoren, die überladen werden können:

Operatoren Notizen
+x, -x, !x, ~x, ++, --, true, false Die Operatoren true und false müssen zusammen überladen werden.
x + y, x - y, x * y, x / y, x % y,
x & y, x | y, x ^ y,
x << y, x >> y, x >>> y
x == y, x != y, x < y, x > y, x <= y, x >= y Müssen wie folgt in Paaren überladen werden: == und !=, < und >, <= und >=.

Nicht überladbare Operatoren

Die folgende Tabelle zeigt die Operatoren, die nicht überladen werden können:

Operatoren Alternativen
x && y, x || y Überladen Sie die Operatoren true und false sowie die Operatoren & oder |. Weitere Informationen finden Sie unter Benutzerdefinierte bedingte logische Operatoren.
a[i], a?[i] Definieren Sie einen Indexer.
(T)x Definieren Sie benutzerdefinierte Typkonvertierungen, die von einem Umwandlungsausdruck ausgeführt werden können. Weitere Informationen finden Sie unter Benutzerdefinierte Konvertierungsoperatoren.
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= Überladen Sie den entsprechenden binären Operator. Wenn Sie beispielsweise den binären +-Operator überladen, wird += implizit überladen.
^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, typeof, with
Keine.

C#-Sprachspezifikation

Weitere Informationen finden Sie in den folgenden Abschnitten der C#-Sprachspezifikation:

Weitere Informationen