Surcharge d’opérateur : opérateurs unaires, arithmétiques, d’égalité et de comparaison prédéfinis

Un type défini par l’utilisateur peut surcharger un opérateur C# prédéfini. Autrement dit, un type peut fournir l’implémentation personnalisée d’une opération si l’un des opérandes (voire les deux) est de ce type. La section Opérateurs surchargeables indique les opérateurs C# qui peuvent être surchargés.

Utilisez le mot clé operator pour déclarer un opérateur. Une déclaration d’opérateur doit respecter les règles suivantes :

  • Elle contient un modificateur public et un modificateur static.
  • Un opérateur unaire possède un paramètre d’entrée. Un opérateur binaire possède deux paramètres d’entrée. Dans chaque cas, au moins un paramètre doit avoir le type T ou T?, où T est le type qui contient la déclaration d’opérateur.

L’exemple suivant définit une structure simplifiée pour représenter un nombre rationnel. La structure surcharge certains des opérateurs arithmétiques :

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

Vous pouvez étendre l’exemple précédent en définissant une conversion implicite de int à Fraction. Les opérateurs surchargés devraient alors prendre en charge les arguments de ces deux types. Autrement dit, il deviendrait possible d’ajouter un entier à une fraction et d’obtenir une fraction en conséquence.

Vous utilisez également le mot clé operator pour définir une conversion de type personnalisée. Pour plus d’informations, consultez Opérateurs de conversion définie par l’utilisateur.

Opérateurs surchargeables

Le tableau suivant répertorie les opérateurs qui peuvent être surchargés :

Opérateurs Notes
+x, -x, !x, ~x, ++, --, true, false Les opérateurs true et false doivent être surchargés ensemble.
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 Doivent être surchargés par paires comme suit : == et !=, < et >, <= et >=.

Opérateurs non surchargeables

Le tableau suivant répertorie les opérateurs qui ne peuvent pas être surchargés :

Opérateurs Autres solutions
x && y, x || y Surchargez à la fois les opérateurs true et false, et les opérateurs & ou |. Pour plus d’informations, consultez Opérateurs logiques conditionnels définis par l’utilisateur.
a[i], a?[i] Définissez un indexeur.
(T)x Définissez des conversions de type personnalisées qui peuvent être exécutées par une expression cast. Pour plus d’informations, consultez Opérateurs de conversion définie par l’utilisateur.
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= Surchargez l’opérateur binaire correspondant. Par exemple, lorsque vous surchargez l’opérateur binaire +, += est implicitement surchargé.
^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
Aucun.

spécification du langage C#

Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :

Voir aussi