Sobrecarga de operadores: operadores unarios, aritméticos, de igualdad y de comparación predefinidos

Un tipo definido por el usuario puede sobrecargar un operador de C# predefinido. Es decir, un tipo puede proporcionar la implementación personalizada de una operación cuando uno o los dos operandos son de ese tipo. En la sección Operadores sobrecargables se muestra qué operadores de C# pueden sobrecargarse.

Use la palabra clave operator para declarar un operador. Una declaración de operador debe cumplir las reglas siguientes:

  • Incluye los modificadores public y static.
  • Un operador unario tiene un parámetro de entrada. Un operador binario tiene dos parámetros de entrada. En cada caso, al menos un parámetro debe ser de tipo T o T? donde T es el tipo que contiene la declaración del operador.

En el ejemplo siguiente se muestra una estructura simplificada para representar un número racional. La estructura sobrecarga algunos de los operadores aritméticos:

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

Puede ampliar el ejemplo anterior mediante la definición de una conversión implícita de int a Fraction. A continuación, los operadores sobrecargados admiten argumentos de esos dos tipos. Es decir, sería posible agregar un valor entero a una fracción y obtener como resultado una fracción.

También usa la palabra clave operator para definir una conversión de tipos personalizada. Para obtener más información, vea Operadores de conversión definidos por el usuario.

Operadores sobrecargables

En la tabla siguiente se muestran los operadores que se pueden sobrecargar:

Operadores Notas
+x, -x, !x, ~x, ++, --, true, false Los operadores true y false deben sobrecargarse juntos.
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 Deben sobrecargarse en parejas de la siguiente manera: == y !=, < y >, <= y >=.

Operadores no sobrecargables

En la tabla siguiente se muestran los operadores que no se pueden sobrecargar:

Operadores Alternativas
x && y, x || y Sobrecargue los operadores true y false, así como los operadores & o |. Para obtener más información, vea Operadores lógicos condicionales definidos por el usuario.
a[i], a?[i] Defina un indizador.
(T)x Defina conversiones de tipos personalizadas que pueden realizarse mediante una expresión de conversión. Para obtener más información, vea Operadores de conversión definidos por el usuario.
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= Sobrecargue el operador binario correspondiente. Por ejemplo, cuando sobrecarga el operador + binario, += se sobrecarga implícitamente.
^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
Ninguno.

Especificación del lenguaje C#

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:

Consulte también