Оператори, що завантажуються , від 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;
}