`+=` 的 C# 运算符重载? [英] C# operator overload for `+=`?

查看:34
本文介绍了`+=` 的 C# 运算符重载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为 += 执行运算符重载,但我不能.我只能为 + 做一个运算符重载.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆