委托探索
一直对于委托理解有点朦胧,今天一时兴起准备一探究竟。首先要准备的工具就是reflector(反编译器)。
1 delegate void SayHiDelegate(string name);
2 void SayNiHao(string name)
3 {
4 Console.WriteLine("你好"+name);
5 }
6 void SayHello(string name)
7 {
8 Console.WriteLine("Hello"+name);
9 }
然后我们先这样调用
1 SayHiDelegate SayHi = null;
2 SayHi = new SayHiDelegate(SayHello);//这里也可以写成SayHi = SayHello
3 SayHi += SayNiHao;//这里实际上为SayHi = (SayHiDelegate) Delegate.Combine(SayHi, new SayHiDelegate(SayNiHao))
然后我们编译下,在反编译下exe文件。来查看Delegate.Combine(SayHi, new SayHiDelegate(SayNiHao))到底是怎么回事?
1 public static Delegate Combine(Delegate a, Delegate b)
2 {
3 if (a == null)
4 {
5 return b;
6 }
7 return a.CombineImpl(b);
8 }
再来查看a.CombineImpl(b)是怎么回事?
1 protected virtual Delegate CombineImpl(Delegate d)
2 {
3 throw new MulticastNotSupportedException(Environment.GetResourceString("Multicast_Combine"));
4 }
这里就让我无路可找了,然后我又发现有个virtual关键字,于是就想看看是否有子类override这个方法。(查看它的Derived Type下)看见果然有个子类叫MulticastDelegate在到MulticastDelegate类里面找CombineImpl(Delegate d)方法,果然找到了。
1 protected sealed override Delegate CombineImpl(Delegate follow);
打开一看晕了,太长了。有点想放弃看了,想到今天的目的还是忍着头皮看下去。看了许久,查了一些资料。发现MulticastDelegate类两个字段
1 private IntPtr _invocationCount;
2 private object _invocationList;
以及MulticastDelegate继承的Delegate的两个字段
1 internal IntPtr _methodPtr;
2 internal object _target;
大概的意思。
_invocationList:表示存储当前委托中的方法数目。
_methodPtr:表示初始化的时候指向的方法
_target:表示初始化的时候指向方法的对象。即this.SayHi();-->this就为_target,SayHi()就为_methodPtr
_invocationList:表示存放方法的数组。
_invocationCount:表示_invocationList个数。
1 protected sealed override Delegate CombineImpl(Delegate follow)
2 {
3 object[] objArray;
4 int num2;
5 if (follow == null)
6 {
7 return this;
8 }
9 if (!Delegate.InternalEqualTypes(this, follow))
10 {
11 throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
12 }
13 MulticastDelegate o = (MulticastDelegate) follow;
14 int num = 1;
15 object[] objArray2 = o._invocationList as object[];
16 if (objArray2 != null)
17 {
18 num = (int) o._invocationCount;
19 }
20 object[] objArray3 = this._invocationList as object[];
21 if (objArray3 == null)
22 {
23 num2 = 1 + num;
24 objArray = new object[num2];
25 objArray[0] = this;
26 if (objArray2 == null)
27 {
28 objArray[1] = o;
29 }
30 else
31 {
32 for (int i = 0; i < num; i++)
33 {
34 objArray[1 + i] = objArray2[i];
35 }
36 }
37 return this.NewMulticastDelegate(objArray, num2);
38 }
这是情形一:
大致的流程:a.CombineImpl(b)
- 如果b==null就返回a也就是说b中没有任何方法,那么a+=b自然为a了;
- 如果b!=null,那么如果b中的_invokationList没有方法,那么b的方法数为num=1;否则num=_invocationCout;
- 然后在计算a的方法总数,如果a==null那么方法总个数num2=num+1,然后在申请一个num2的数组大小,将a,b中的方法所在的委托对象的地址存入。最后在重新生成一个委托作为返回值。