这两天把前段时间已经粗略看完的ms .net框架程序设计又拣了几章来精读,发现了一个不大不小的问题,就是关于委托对象的判等!
先看一段代码: //定义了一个基类,其中有委托Feedback的定义,参照原书的部分代码
 1#endregion

下面一段是入口函数调用的部分//调用InvokeDelegate()
 1Delegate中判等的一个疑问~        private static void InvokeDelegate()
 2        }

最后的输出是这样的
0
True
Processing Item 0 to MessageBox of 1:0
Processing Item 0 to MessageBox of 1:0
Processing Item 0 to MessageBox of 1:0
False

After Invokeration,the return value is 2
Press any key to continue

这样就有一个问题了,首先要说明的是:System.Delegate从System.Object继承而来,而System.MulticastDelegate继承而来.
Delegate改写了Object的虚方法Equals(比较的是两个委托对象的_target字段和_method字段),而System.MulticastDelegate又改写了Delegate的虚方法Equals(在Delegate的基础上,增加了对_prev字段的比较)

因为委托对象FbObj1和FbObj2在定义的时候都是一个新对象,而且都是从MulticastDelegate继承而来的,并且此时都还没有_prev的指向,也就是说_prev都指向为空,所以在FbChain把该二对象Combine之前,有Console.WriteLine(FbObj1==FbObj2)的值为True的话,都还很好理解,因为_prev均为空,且其他两个字段也相等。

但是在用FbChain这个对象把二者Combine之后,对他们的相等与否,就似乎有点说不过去了,按照书上的说法,应该是FbObj2的_prev已经指向了FbObj1(此时FbObj1的_prev字段当然仍然为null)因为如果FbObj2的_prev字段不改变的话,那么递归调用函数指针的说法就有点难自圆其说了,因为Feedback委托类的内部实现就是对Invoke方法的递归调用.

然而,FbObj1和FbObj2两者又都是继承自MulticastDelegate类的,虚方法Equals已经被改写,那么在这里调用'==' ,按照类的继承思想来说,就应该还把_prev字段考虑进去,那么,输出的结果应该为False!但是实际上还是True!为什么?

疑问之二: 在FbChain把FbObj1和FbObj2两者Combine之后,实际的内部情况应该是FbChain这个Feedback委托对象的_prev对象指向了FbObj2,从而在内部的Invoke方法中,有如下的调用

if(_prev!=null)_prev.Invoke(value,item,numItems);//伪代码,形成递归调用

那么,从这点上来说,FbChain的_prev(同时也是一个MulticastDelegate对象)是应该指向FbObj2的,Combine方法是把两个_prev为空的委托对象连接成委托链之后,返回委托链的尾巴,赋给FbChain,那么,FbChain是FbObj2的拷贝(替身)还是一个新的Feedback委托对象?

后面的代码又构造了一个FbChain2对象,同样,把FbObj2和FbChain两者Combine到了一条链上,(顺便说下,写这篇log的时候,我自己觉得是不是有点莫名其妙的,因为此时FbChain对象已经存在了,是拷贝还是新对象,我还不得而知),按照Delegate中Combine 方法的设计初衷,是把两个_prev为null的委托对象链到一起,而这里,两者(FbObj2和FbChain)的_prev字段都不是null !

那么,这里,按照我的想法,FbChain2的_prev字段就应该是指向FbChain的,按照文中的说法,FbChain的_prev应该是指向FbObj2对象的,这点我认同(因为符合new操作符的含义)同时,FbChain的_prev又是指向FbObj2的,从某种意义上来说,FbChain2的_prev应该是等于FbChain的_prev的! 但是这里的测试表明,他们是不相等的!为什么?如果把上面的第二段代码改一下,如下:

Delegate中判等的一个疑问~        private static void InvokeDelegate()
        }

//output
Processing Item 0 to MessageBox of 1:0//FbObj2
Processing Item 0 to Console of 1:0//FbObj1
Processing Item 0 to MessageBox of 1:0//FbObj2
貌似又有问题了,理论结果应该是
Processing Item 0 to MessageBox of 1:0//FbChain or FbObj2,i thinkDelegate中判等的一个疑问~
Processing Item 0 to MessageBox of 1:0//FbObj2
Processing Item 0 to Console of 1:0//FbObj1
怎么可能会是上面的输出呢??
-----------------------------
测试环境:windows xp+sp2
vs .net 2003

ps.原本我以为不用GetInvokeList方法也是可以得到单个委托对象的返回值的,结果证明这里是我错了,虽然从单步调试中确实可以看出这里是调用了三次委托,但最后确实也只返回最后一个委托的值!如果.net环境能让开发者深入其类的内部,或许我这里的代码就可以返回单个委托的返回值了Delegate中判等的一个疑问~

相关文章:

  • 2022-01-02
  • 2022-12-23
  • 2021-11-05
  • 2021-11-27
  • 2021-05-31
  • 2021-08-05
  • 2021-06-18
猜你喜欢
  • 2021-09-10
  • 2021-12-18
  • 2021-09-21
  • 2022-01-12
  • 2022-12-23
  • 2022-12-23
  • 2021-07-17
相关资源
相似解决方案