`+=` 的 C# 运算符重载? [英] C# operator overload for `+=`?
问题描述
我正在尝试为 +=
执行运算符重载,但我不能.我只能为 +
做一个运算符重载.
I am trying to do operator overloads for +=
, but I can't. I can only make an operator overload for +
.
怎么会?
编辑
这不起作用的原因是我有一个 Vector 类(带有 X 和 Y 字段).考虑以下示例.
The reason this is not working is that I have a Vector class (with an X and Y field). Consider the following example.
vector1 += vector2;
如果我的运算符重载设置为:
If my operator overload is set to:
public static Vector operator +(Vector left, Vector right)
{
return new Vector(right.x + left.x, right.y + left.y);
}
那么结果将不会被添加到vector1中,而是vector1也会通过引用成为一个全新的Vector.
Then the result won't be added to vector1, but instead, vector1 will become a brand new Vector by reference as well.
推荐答案
可重载运算符,来自 MSDN:
赋值运算符不能被重载,但是例如+=
是使用+
求值的,它可以被重载.
Assignment operators cannot be overloaded, but
+=
, for example, is evaluated using+
, which can be overloaded.
更重要的是,任何赋值运算符都不能重载.我认为这是因为垃圾收集和内存管理会产生影响,这是 CLR 强类型世界中潜在的安全漏洞.
Even more, none of assignment operators can be overloaded. I think this is because there will be an effect for the Garbage collection and memory management, which is a potential security hole in CLR strong typed world.
尽管如此,让我们看看运算符到底是什么.根据著名的Jeffrey Richter 的书,每种编程语言有自己的操作符列表,这些列表是在一个特殊的方法调用中编译的,而 CLR 本身对操作符一无所知.那么让我们看看 +
和 +=
运算符后面到底是什么.
Nevertheless, let's see what exactly an operator is. According to the famous Jeffrey Richter's book, each programming language has its own operators list, which are compiled in a special method calls, and CLR itself doesn't know anything about operators. So let's see what exactly stays behind the +
and +=
operators.
看这个简单的代码:
Decimal d = 10M;
d = d + 10M;
Console.WriteLine(d);
让我们查看此指令的 IL 代码:
Let view the IL-code for this instructions:
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
现在让我们看看这段代码:
Now lets see this code:
Decimal d1 = 10M;
d1 += 10M;
Console.WriteLine(d1);
以及用于此的 IL 代码:
And IL-code for this:
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# 中的语法糖,您可以简单地重载 +
运算符.
They are equal! So the +=
operator is just syntactic sugar for your program in C#, and you can simply overload +
operator.
例如:
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;
}
此代码将被编译并成功运行为:
This code will be compiled and successfully run as:
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 所说,您确实应该将向量作为不可变对象.两个向量相加的结果是一个新的向量,而不是第一个大小不同的向量.
According to your Update - as the @EricLippert says, you really should have the vectors as an immutable object. Result of adding of the two vectors is a new vector, not the first one with different sizes.
如果由于某种原因你需要改变第一个向量,你可以使用这个重载(但对我来说,这是非常奇怪的行为):
If, for some reason you need to change first vector, you can use this overload (but as for me, this is very strange behaviour):
public static Vector operator +(Vector left, Vector right)
{
left.x += right.x;
left.y += right.y;
return left;
}
这篇关于`+=` 的 C# 运算符重载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!