Overload degli operatori : operatori unari, aritmetici, di uguaglianza e di confronto predefiniti

Un tipo definito dall'utente può eseguire l'overload di un operatore C# definito in precedenza. In altri termini, un tipo può fornire l'implementazione personalizzata di un'operazione quando uno o entrambi gli operandi sono di quel tipo. La sezione Operatori che supportano l'overload illustra gli operatori C# che possono essere sottoposti a overload.

Per dichiarare un operatore, usare la parola chiave operator. Una dichiarazione di operatore deve soddisfare le regole seguenti:

  • Include sia un modificatore public che un modificatore static.
  • Un operatore unario ha un parametro di input. Un operatore binario ha due parametri di input. In entrambi i casi almeno un parametro deve essere di tipo T o T?, dove T è il tipo che contiene la dichiarazione dell'operatore.

L'esempio seguente definisce una struttura semplificata per la rappresentazione di un numero razionale. La struttura esegue l'overload di alcuni operatori aritmetici:

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

È possibile estendere l'esempio precedente definendo una conversione implicita da int in Fraction. Gli operatori di overload supporteranno quindi gli argomenti di questi due tipi. Diventerà quindi possibile aggiungere un numero intero a una frazione e ottenere di conseguenza una frazione.

È anche possibile usare la parola chiave operator per definire una conversione del tipo personalizzata. Per altre informazioni, vedere Operatori di conversione definiti dall'utente.

Operatori che supportano l'overload

La tabella seguente mostra gli operatori che possono essere sottoposti a overload:

Operatori Note
+x, -x, !x, ~x, ++, --, true, false Gli operatori true e false devono essere sottoposti a overload insieme.
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 Deve essere sottoposto a overload in coppie come indicato di seguito: == e !=, < e >, <= e >=.

Operatori che non supportano l’overload

La tabella seguente illustra gli operatori che non possono essere sottoposti a overload:

Operatori Alternative
x && y, x || y Eseguire l'overload sia degli operatori true chee false e sia degli operatori & o |. Per ulteriori informazioni, consultare Operatori logici condizionali definiti dall'utente.
a[i], a?[i] Definire un indicizzatore.
(T)x Definire conversioni di tipi personalizzate che possono essere eseguite da un'espressione cast. Per altre informazioni, vedere Operatori di conversione definiti dall'utente.
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= Eseguire l'overload dell'operatore binario corrispondente. Ad esempio, quando si esegue l'overload dell'operatore binario +, viene eseguito l'overload implicito di +=.
^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
Nessuno.

Specifiche del linguaggio C#

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:

Vedi anche