可重载的运算符,来自微软MSDN:
赋值运算符不能被重载,但是例如+=
会使用可以被重载的+
进行计算。
此外,所有的赋值运算符都不能被重载。我认为这是因为在CLR强类型的世界中,这将导致垃圾回收和内存管理方面的影响,这可能是一个潜在的安全漏洞。
不过,让我们看看运算符到底是什么。根据著名的Jeffrey Richter的书所说,每种编程语言都有其自己的操作符列表,它们被编译成特殊的方法调用,而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;
}