Перегружаемые операторы из 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;
}