La sobrecarga de operadores nos permite redefinir la funcionalidad de los operadores estándar (como +
, -
, *
, /
, ==
, !=
…) para trabajar con tipos definidos por nosotros mismos.
Esto nos permite hacer que los objetos de estos tipos que definimos sean manipulados de manera natural y sencilla, similar a los tipos primitivos.
Para sobrecargar un operador en C#, se debe definir un método estático con el modificador operator
seguido del operador que se desea sobrecargar. La firma del método debe coincidir con los operandos del operador.
public static TipoDeDato operator Operador(TipoDeDato operando1, TipoDeDato operando2)
{
// Implementación del comportamiento personalizado
}
- TipoDeDato: Es el tipo de dato para el cual se está sobrecargando el operador.
- Operador: Es el operador que se desea sobrecargar.
- operando1, operando2: Son los operandos sobre los cuales se aplicará el operador.
Sobrecarga de operadores aritméticos
Es posible sobrecargar los operadores +
, -
, *
, /
. Vamos a verlo con un ejemplo 👇.
Supongamos que tenemos una estructura Vector2D
que representa un vector en dos dimensiones. Queremos sobrecargar el operador +
para sumar dos vectores.
public struct Vector2D
{
public double X { get; }
public double Y { get; }
public Vector2D(double x, double y)
{
X = x;
Y = y;
}
public static Vector2D operator +(Vector2D v1, Vector2D v2)
{
return new Vector2D(v1.X + v2.X, v1.Y + v2.Y);
}
}
En este ejemplo,
- El método estático
operator +
toma dosVector2D
como parámetros - Devuelve un nuevo
Vector2D
que es la suma de los dos vectores
Uso de la sobrecarga del operador
Ahora vamos a ver como usamos nuestra sobrecarga del operador. Para ello, instanciamos dos Vector2D
y les aplicamos el operador +
.
Vector2D v1 = new Vector2D(1.0, 2.0);
Vector2D v2 = new Vector2D(3.0, 4.0);
Vector2D result = v1 + v2;
Console.WriteLine($"Resultado: ({result.X}, {result.Y})");
La salida de este código será:
Resultado: (4.0, 6.0)
Es decir, el operador sobrecargado +
ha invocado el método estático que habíamos definido, para aplicar la suma a nuestros dos vectores. Mientras que el uso es sencillo e intuitivo.
Sobrecarga de operadores relacionales
Además de los operadores aritméticos, también es posible sobrecargar operadores relacionales como ==
y !=
. Para ello, también deberemos sobrecargar el método Equals
y GetHashCode
para mantener la coherencia.
Veámoslo con un ejemplo,
public struct Vector2D
{
public double X { get; }
public double Y { get; }
public Vector2D(double x, double y)
{
X = x;
Y = y;
}
public static bool operator ==(Vector2D v1, Vector2D v2)
{
return v1.X == v2.X && v1.Y == v2.Y;
}
public static bool operator !=(Vector2D v1, Vector2D v2)
{
return !(v1 == v2);
}
public override bool Equals(object obj)
{
if (obj is Vector2D)
{
Vector2D v = (Vector2D)obj;
return X == v.X && Y == v.Y;
}
return false;
}
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
}
}
Uso de la sobrecarga de operadores relacionales
Una vez sobrecargados los operadores, el uso es muy sencillo. Volviendo a nuestra clase Vector2D
, quedaría así,
Vector2D v1 = new Vector2D(1.0, 2.0);
Vector2D v2 = new Vector2D(1.0, 2.0);
Vector2D v3 = new Vector2D(3.0, 4.0);
Console.WriteLine(v1 == v2); // True
Console.WriteLine(v1 != v3); // True