Операторы с перегрузкой , от MSDN:
Операторы присваивания не могут быть перегружены, но, например, +=
оценивается с использованием +
, который может быть перегружен.
Более того, ни один из операторов присваивания не может быть перегружен. Я думаю, это потому, что это повлияет на сборку мусора и управление памятью, что является потенциальной дырой в безопасности в мире строгой типизации CLR.
Тем не менее, давайте посмотрим, что такое оператор. Согласно известной книге Джеффри Рихтера , каждый язык программирования имеет свой собственный список операторов, которые компилируются в вызовы специальных методов, а сам CLR ничего не знает об операторах. Итак, давайте посмотрим, что именно стоит за операторами +
и +=
.
См. Этот простой код:
Decimal d = 10M;
d = d + 10M;
Console.WriteLine(d);
Позвольте просмотреть IL-код для этой инструкции:
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
Теперь давайте посмотрим этот код:
Decimal d1 = 10M;
d1 += 10M;
Console.WriteLine(d1);
И IL-код для этого:
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
Они равны! Таким образом, оператор +=
является просто синтаксическим сахаром для вашей программы в C # , и вы можете просто перегрузить оператор +
.
Например:
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;
}
Этот код будет скомпилирован и успешно запущен как:
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
Обновление:
Согласно вашему Обновлению - как говорит @EricLippert, вы действительно должны иметь векторы как неизменный объект. Результатом добавления двух векторов является новый вектор, а не первый с разными размерами.
Если по какой-то причине вам необходимо изменить первый вектор, вы можете использовать эту перегрузку (но для меня это очень странное поведение):
public static Vector operator +(Vector left, Vector right)
{
left.x += right.x;
left.y += right.y;
return left;
}