多播委托浅析

饮水思源

http://www.cnblogs.com/huashanlin/archive/2008/03/11/1100870.html

Overview

本文主要,来学习一下,多播委托 , 这个名词可能比较生僻一点,通过语言很难表达出来,下面我们还是通过代码来说明吧,我本身对这些概念性的东西,就不太感冒...露怯了。

多播委托

  • 一个委托对象,包含一个以上的方法被称为多播委托。

Demo

一个简单的委托

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnderstandDelegate
{
    public delegate void SayHelloHandler();
}

Person类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnderstandDelegate
{

    public class Person
    {
        public void SayHello(SayHelloHandler handler)
        {
            handler.Invoke();
        }
    }
}

调用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnderstandDelegate
{
    class Program
    {
        static void Main(string[] args)
        {
            //想不到还有这种操作吧
            SayHelloHandler handler = ChinaStyleSayHello;
            handler += EnglishStyleSayHello;
            handler += JapanStyleSayHello;

            new Person().SayHello(handler);

        }

        static void ChinaStyleSayHello()
        {
            Console.WriteLine("你好");
        }

        static void EnglishStyleSayHello()
        {
            Console.WriteLine("Hello");
        }

        static void JapanStyleSayHello()
        {
            Console.WriteLine("坑你急哇");
        }
    }
}

输出结果

你好
Hello
坑你急哇

好,这就是我们的多播委托 ![img](file:///C:\Users\IT\AppData\Local\Temp\SGPicFaceTpBq\20744\AC263C29.png), 概念性的东西太难理解了.

多播委托浅析

还记得我们分析,委托原理的时候,说过的委托的继承关系吗:

自定义委托 继承自 MulticastDelegate 继承自 Delegate .

现在我们来看一看 MulticastDelegate 类。

其中我们需要值得注意的方法

//移除一个委托元素从这个多播委托的tion list中。
[SecuritySafeCritical]
protected sealed override Delegate RemoveImpl(Delegate value);
//将一个该委托和一个指定的委托联合起来,产生一个新的委托对象。
[SecuritySafeCritical]
protected sealed override Delegate CombineImpl(Delegate follow);
//返回多播委托的列表,以调用的顺序排序
[SecuritySafeCritical]
public sealed override Delegate[] GetInvocationList();

看一看反编译

static void Main(string[] args)
{
    //想不到还有这种操作吧
    SayHelloHandler handler = ChinaStyleSayHello;
    handler += EnglishStyleSayHello;
    handler += JapanStyleSayHello;
    new Person().SayHello(handler);
}
//被反编译为了如下代码
private static void Main(string[] args)
{
	SayHelloHandler sayHelloHandler = new SayHelloHandler(Program.ChinaStyleSayHello);
	sayHelloHandler = (SayHelloHandler)Delegate.Combine(sayHelloHandler, new SayHelloHandler(Program.EnglishStyleSayHello));
	sayHelloHandler = (SayHelloHandler)Delegate.Combine(sayHelloHandler, new SayHelloHandler(Program.JapanStyleSayHello));
	new Person().SayHello(sayHelloHandler);
}

我们的+= 运算,最后编译成了 调用Delegate.Combine 静态方法的形式,我们的编译器真是太智能了,我们来看一下Delegate.Combine 方法的源码,又用到了我们 强大又免费的ILSpy 工具了。

public static Delegate Combine(Delegate a, Delegate b)
{
	if (a == null)
	{
		return b;
	}
  	//最后还是调用了我们的 MulticastDelegate类中的CombineImpl方法
	return a.CombineImpl(b);
}

或许这里你可能有以为,这里不是调用的是Delegate类的方法吗? 不 请注意: Delegate 类的CombineImpl 方法是一个虚方法,MulticastDelegate 类重写了他,因为所有的委托都遵循着这样的继承规律:自定义委托 继承自 MulticastDelegate 继承自 Delegate .

在这里看着是调用的Delegate类的CombineImpl 方法,但是由于MulticastDelegate 类重写了该方法,所以,这里本质上调用的 MulticastDelegate 类的方法。

结语

本章的内容就到这里,如果还有好奇,可以继续通过我们的ILSpy 工具,往深处研究,这里就不在赘述。毕竟笔者水平也有限。

posted @ 2017-09-12 21:39  鲁迅认识的那只猹  阅读(195)  评论(0编辑  收藏  举报