C#中自增、自减操作符重载是个怎么回事儿

开发 后端
对于C#中的自增、自减操作符重载,无论前缀式或是后缀式,都统统只需要一个实现。本文主要介绍的是C#中的自增自减操作符的重载,希望对你有帮助,一起来看。

C#中,重载自增自减操作符的语法并没有什么特殊之处,如下:

  1. public static SomeType operator ++(SomeType some)  
  2. {   
  3. //具体实现  

对于C#中的自增、自减操作符重载,无论前缀式或是后缀式,都统统只需要一个实现。也就是说无论我是这样:someType++,还是这样:++someType使用SomeType类型的自增重载,上述代码中的实现都完全足够完成任务。但是,前缀式++与后缀式++的行为毕竟不同,为什么他们只需要一份同样的实现就可以达到我们需要的目的了呢?

另外,重载操作符的第一原则就是不应该改变操作数对象,而应该返回一个新的对象。否则不仅很可能会令那些使用我们的重载操作符的客户产生困惑,而且更有可能会在调试代码的时候出现意想不到的情况。那么对于自增和自减操作符,我们是否也需要遵从此原则呢?我们又怎么能在不修改操作数的情况下,对操作数自增或者自减呢?考虑如下的实现:

  1. class SomeType   
  2. {   
  3. public int Number   
  4. getset;  
  5. }   
  6. public static SomeType operator ++(SomeType s)   
  7. {  
  8. s.Number++;   
  9. return s;   
  10. }} 

这里直接修改了操作数,并且直接返回了修改之后的操作数实例。

当我们使用SomeType的前缀自增重载时:

  1. SomeType instance = new SomeType();  
  2. instance.Number = 1;  
  3. ++instance; 

如我们所预料的,操作符重载的方法体会被执行。而且instance也确实会按照理想的方式自增。我们再来看后缀自增操作:

  1. SomeType instance1 = new SomeType();  
  2. instance1.Number = 1;  
  3. SomeType instance2 = instance1++; 

不严谨的思维让我们很容易认为,现在instance1的Number应该是2,而instance2的Number应该是1。但是,事不如人愿,实际上现在的instance1和instance2的Number都是2!

这到底是为什么呢?

其实是这样的,相比其他我们司空见惯的重载操作符如+和-,编译器会对重载的自增和自减操作符做一些额外的处理。在我们使用自增重载的时候,如++instance,++重载的方法体会被执行。然而我们没有想到的是,在操作符重载方法被执行完成之后,instance会被自动赋值为操作符重载方法的返回值!而这一切都是编译的时候就安排好了的。

也就是说,如果SomeType是引用类型,则在执行完++instance语句之后,instatnce会指向那个被自增重载操作符方法所返回的对象实例。而如果SomeType是值类型,那么instance会被按照C#值类型的标准赋值方式被重载操作符方法返回的值类型赋值,也就是逐字段赋值。

当我们使用前缀式时,这一切都工作的很好。但是当我们使用后缀式时,问题就来了。在上面的使用后缀自增的例子里,首先执行了instance1的自增操作,不过接下来,实际上是使用了instance1在执行自增操作前的一个副本(对于引用类型,使用引用的副本;对于值类型,使用整个结构的副本)来对instance2赋值的。

因为我们在SomeType的自增重载的实现中,直接对操作数进行了修改,并且返回了原操作数。所以这样一来,现在instance1和instance2现在指向的都是原操作数的实例,他们有同样的Number也就不足为怪了。

另一个SomeType的自增重载版本是这样的:

  1. public static SomeType operator ++(SomeType s)   
  2. {   
  3. var result = new SomeType();   
  4. result.Number++;   
  5. return result;   

这个版本的实现遵循了“不应该在操作符重载中修改操作数”的原则。如果使用了这个版本的自增重载,在上述后缀式自增的例子中,会和我们预期的一样:instance1的Number是2,而instance1的Number是1。

我想,在很多情况下(特别是当SomeType是值类型时),这会是您希望得到的结果,也同样是您代码的消费者所预期的结果。

好吧,对于自增和自减操作符,我们这样理解可能会更容易一些:例如语句“instance2 = instance1++;”,并不是将自增重载方法的返回值赋值给左值instance2,而是将自增重载方法的返回值赋值给instance1。

注意:自增重载方法的返回值是用来赋值给调用该重载方法的操作数的!(如果您有C++的背景,这一点可能不太容易接受)

【编辑推荐】

  1. C#控件的闪烁问题解决方法总结
  2. C#简单游戏外挂制作(以Warcraft Ⅲ为例)
  3. 使用托管C++粘合C#和C++代码(一)
  4. 使用托管C++粘合C#和C++代码(二)
  5. 利用C#实现任务栏通知窗口
责任编辑:于铁 来源: 博客园
相关推荐

2009-08-18 17:55:20

C#操作符重载

2021-07-30 07:28:16

伪类伪元素CSS

2017-11-24 11:10:38

区块链矿工分叉

2009-08-18 18:06:54

C#操作符重载

2021-11-01 15:35:31

C++自增自减

2018-05-08 08:46:47

Linux内存释放

2009-08-18 17:42:12

C#操作符重载

2018-01-25 16:07:41

匿名函数自执行

2009-08-18 17:20:17

C#操作符重载

2009-08-18 17:34:25

C#操作符重载应用

2009-08-19 17:26:28

C# 操作符

2020-07-09 09:56:48

Python语言开发

2009-08-21 09:30:05

is和as操作符

2023-12-26 01:09:28

MySQL存储释放锁

2009-08-19 17:20:22

C# 操作符

2010-02-05 10:30:02

C++操作符重载

2009-07-14 18:34:22

Jython操作符重载

2010-02-03 10:23:47

C++操作符重载

2021-07-07 05:37:57

邮件安全网络攻击数据泄露

2009-08-19 17:13:15

C# 操作符基础知识
点赞
收藏

51CTO技术栈公众号