Operadores sobrecargables , de MSDN:
Los operadores de asignación no se pueden sobrecargar, pero +=
, por ejemplo, se evalúan utilizando +
, que puede sobrecargarse.
Aún más, ninguno de los operadores de asignación puede estar sobrecargado. Creo que esto se debe a que habrá un efecto para la recolección de basura y la administración de memoria, que es un potencial agujero de seguridad en el mundo CLR de tipo fuerte.
Sin embargo, veamos qué es exactamente un operador. Según el famoso libro de Jeffrey Richter , cada lenguaje de programación tiene su propia lista de operadores, que se compilan en un método especial de llamadas, y CLR en sí no sabe nada sobre operadores. Así que veamos qué queda exactamente detrás de los operadores +
y +=
.
Vea este código simple:
Decimal d = 10M;
d = d + 10M;
Console.WriteLine(d);
Veamos el código IL para estas instrucciones:
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.s 10
IL_000c: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0011: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0016: stloc.0
Ahora veamos este código:
Decimal d1 = 10M;
d1 += 10M;
Console.WriteLine(d1);
Y código IL para esto:
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.s 10
IL_000c: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0011: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
valuetype [mscorlib]System.Decimal)
IL_0016: stloc.0
¡Son iguales! Entonces, el +=
operador es solo azúcar sintáctico para su programa en C # , y puede simplemente sobrecargar al +
operador.
Por ejemplo:
class Foo
{
private int c1;
public Foo(int c11)
{
c1 = c11;
}
public static Foo operator +(Foo c1, Foo x)
{
return new Foo(c1.c1 + x.c1);
}
}
static void Main(string[] args)
{
Foo d1 = new Foo (10);
Foo d2 = new Foo(11);
d2 += d1;
}
Este código se compilará y se ejecutará correctamente como:
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newobj instance void ConsoleApplication2.Program/Foo::.ctor(int32)
IL_0008: stloc.0
IL_0009: ldc.i4.s 11
IL_000b: newobj instance void ConsoleApplication2.Program/Foo::.ctor(int32)
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: ldloc.0
IL_0013: call class ConsoleApplication2.Program/Foo ConsoleApplication2.Program/Foo::op_Addition(class ConsoleApplication2.Program/Foo,
class ConsoleApplication2.Program/Foo)
IL_0018: stloc.1
Actualizar:
De acuerdo con su Actualización, como dice @EricLippert, realmente debería tener los vectores como un objeto inmutable. El resultado de la suma de los dos vectores es un nuevo vector, no el primero con diferentes tamaños.
Si, por alguna razón, necesita cambiar el primer vector, puede usar esta sobrecarga (pero para mí, este es un comportamiento muy extraño):
public static Vector operator +(Vector left, Vector right)
{
left.x += right.x;
left.y += right.y;
return left;
}