Operatory z możliwością przeciążenia z możliwością , z MSDN:
Operatory przypisania nie mogą być przeciążane, ale +=
na przykład są oceniane przy użyciu +
, które mogą zostać przeciążone.
Co więcej, żaden z operatorów przypisania nie może być przeciążony. Myślę, że dzieje się tak, ponieważ będzie to miało wpływ na zbieranie śmieci i zarządzanie pamięcią, co jest potencjalną luką w zabezpieczeniach w świecie silnie typizowanym CLR.
Niemniej jednak zobaczmy, czym dokładnie jest operator. Według słynnej książki Jeffreya Richtera , każdy język programowania ma swoją własną listę operatorów, która jest kompilowana w specjalnych wywołaniach metod, a sam CLR nie wie nic o operatorach. Zobaczmy więc, co dokładnie pozostaje za operatorami +
i +=
.
Zobacz ten prosty kod:
Decimal d = 10M;
d = d + 10M;
Console.WriteLine(d);
Zobaczmy kod IL dla tej instrukcji:
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
Teraz zobaczmy ten kod:
Decimal d1 = 10M;
d1 += 10M;
Console.WriteLine(d1);
I kod IL do tego:
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
Są równi! Więc +=
operator jest tylko cukrem syntaktycznym dla twojego programu w C # i możesz po prostu przeładować+
.
Na przykład:
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;
}
Ten kod zostanie skompilowany i pomyślnie uruchomiony jako:
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
Aktualizacja:
Zgodnie z twoją aktualizacją - jak mówi @EricLippert, naprawdę powinieneś mieć wektory jako niezmienny obiekt. Efektem dodania dwóch wektorów jest nowy wektor, a nie pierwszy o różnych rozmiarach.
Jeśli z jakiegoś powodu musisz zmienić pierwszy wektor, możesz użyć tego przeciążenia (ale jak dla mnie jest to bardzo dziwne zachowanie):
public static Vector operator +(Vector left, Vector right)
{
left.x += right.x;
left.y += right.y;
return left;
}