【问题标题】:Why cant i overload the += operator in C#? But i still can use it? [duplicate]为什么我不能重载 C# 中的 += 运算符?但是我还能用吗? [复制]
【发布时间】:2011-07-09 08:10:04
【问题描述】:

可能重复:
Simple way to overload compound assignment operator in C#?

我在玩各种事件,认为事件很奇怪。为什么我不能在通用类中实现它们。所以我尝试并发现我不能过载+=。 From the language specs found here

The overloadable unary operators are:    
+   -   !   ~   ++   --   true   false

The overloadable binary operators are:    
+   -   *   /   %   &   |   ^   <<   >>   ==   !=   >   <   >=   <=

+= 未列出。现在,在你说没有理由重载 += 之前,我想提出一个事实,即 C# 有使用 += 运算符的事件,以及我试图实现一个有趣的事件并想使用 += 运算符的事实。现在,我感觉有人会说这就是事件存在的原因,因为这是唯一的原因。但是我想提出您可以将 += 与 TimeSpan 结构一起使用。去试试吧,var ts= new TimeSpan(); ts += ts; 会编译运行。

我查看了 TimeSpan 定义,但我不知道它是如何允许的。我看到了一个看起来很可疑的public static TimeSpan operator +(TimeSpan t);,但后来我意识到它类似于var name = +ts;,就像你可以用var name = -ts; 进行否定一样。

所以我的问题是,我如何将 += 用于我的结构或类。它似乎受到支持,我似乎无法找到它的文档。

【问题讨论】:

    标签: c# .net operator-overloading


    【解决方案1】:

    事件不会重载 +=-= 运算符。这只是在 C# 编译器中硬编码,将其转换为该事件的添加/删除方法。

    您只能重载+-,然后间接重载+=-=。如果您重载+,那么x += y 会自动重载为x = x + y。因此,对于您的类型,您无需进行任何额外的工作。只需超载+,您将免费获得+=。这当然需要左侧参数和结果类型兼容,但通常情况就是这样。


    不能单独重载+= 的原因很可能是它为引用类型创建了奇怪的语义。如果+= 修改了左侧的现有实例,则以下代码的行为会很奇怪:

    MyClass x=new MyClass();
    MyClass y=x;
    x+=SomeThing;
    y has changed now too
    

    另一方面,+= 表示x = x+y,这段代码创建了一个新实例,它分配给 x。并且原始实例在 y 中保持不变;


    另一方面,在 C++ 中,可以安全地为 += 指定单独的重载,因为您可以同时重载赋值和复制构造函数,并使用它来获得正确的语义。

    【讨论】:

    • 很好的答案,您准确地解释了为什么 += 不能被重载,并给了我真正有意义的推理!
    • 也许你也知道这个问题的答案? stackoverflow.com/questions/5203093
    • 单独重载 += 可能会产生奇怪的语义,但它也会允许类型以线程安全的方式执行读取和回写 [e.g. event += someDelegate;以线程安全的方式实现,可以编码void myThing.AddTo(ref myThing dest, myThing src); 以使myThing.AddTo(ref someSharedField, someData) 安全,但不能使someSharedField = someSharedField + someData; 本质上是线程安全的。由于无法将 += 映射到采用 ref 参数的方法,它不能以固有的线程安全方式使用,除了事件。
    【解决方案2】:

    += 运算符不能重载 直接,但用户定义的类型可以 重载 + 运算符。

    使用 += 赋值的表达式 运算符,例如 Copy

    x += y

    相当于复制

    x = x + y

    Msdn

    【讨论】:

      【解决方案3】:

      += 只是加法的简写,然后是赋值。您可以重载+ 运算符,这也使+= 运算符起作用:

      这样编译

      class P 
      {
          public static P operator +(P rhs, P lhs) {
              return null;
          }   
      }
      
      void Main()
      {
          P p = new P();
          p += new P();
      }
      

      (当然,--= 运算符反之亦然)。

      【讨论】:

        【解决方案4】:

        文档不会说谎。不能重载 += 运算符。

        += 运算符只是使用+ 运算符的快捷方式。像x += y 这样的操作会被编译器翻译成x = x + y

        因此,要更改 += 运算符的功能,您必须重载 + 运算符。

        【讨论】:

          猜你喜欢
          • 2020-03-25
          • 2015-11-13
          • 1970-01-01
          • 2011-09-30
          • 2018-03-16
          • 1970-01-01
          • 2011-02-07
          • 2017-09-06
          相关资源
          最近更新 更多