Die wichtigsten arithmetischen und Vergleichsoperatoren kannst du für deine eigenen Klassen und Structs anpassen. Man nennt das Operatorüberladung.
Dieser Artikel behandelt ausführlich die Syntax und geht darauf ein, welche Operatoren überladen werden können und welche nicht.
Die meisten Operatoren haben die Form:
static <return type> operaator <operator symbols>(<parameters>);
Cast-Operatoren haben die Form:
static (explicit|implicit) operator <cast-to-type>(<cast-from-type> <parameter name>);
Operatoren verhalten sich wie statische Methoden.
Syntaxbeispiele:
struct Point
{
decimal x;
decimal y;
public static bool operator ==(Point pt, Point ptOther)
{
return pt.x == ptOther.x && pt.y == ptOther.y;
}
public static bool operator !=(Point pt, Point ptOther)
{
return !(pt == ptOther);
}
public static Point operator *(Point pt, decimal scale)
{
var ptNew = new Point();
ptNew.x = pt.x * scale;
ptNew.y = pt.y * scale;
return ptNew;
}
public static implicit operator Point((decimal x, decimal y) xy)
{
var pt = new Point();
pt.x = xy.x;
pt.y = xy.y;
return pt;
}
public static explicit operator (decimal x, decimal y)(Point pt)
{
return (pt.x, pt.y);
}
}
Oft ist es sinnvoll, eine Equals()-Methode zu implementieren und sie aus dem ==-Operator heraus aufzurufen. Für Vergleiche kannst du außerdem das Interface IComparable implementieren. In beiden Fällen schlägst du zwei Fliegen mit einer Klappe.
Du solltest beachten, dass du keine Operatoren aus Symbolen erstellen kannst, die nicht zum Standardsatz der Operatoren gehören. Du kannst nur vorhandene Symbole für die Operationen verwenden, für die die Dokumentation angibt, dass sie überladen werden können. Welche Operatoren überladen werden können, ist hier aufgelistet.
Beachte, dass die Reihenfolge der Parameter wichtig ist, wenn sie sich im Typ unterscheiden. Im obigen Beispielcode ist pt * 10m ein gültiger Ausdruck, während 10m * pt nicht kompiliert wird.
Diese Dokumentation zu Operatorüberladung beschreibt die Syntax im Detail.