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 einenstatic
-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
oderT?
sein, wobeiT
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: