一、托付的来历
在C++中有各种各样的指针。当中,有一种指针是指向函数或者说是指向方法的。我们能够通过调用这个指针来调用其指向的方法。可是,这种指针是不安全的。假设我们简单的把C++的指针觉得是一个记录内存地址的空间。那么。方法指针里记录的就是目标方法的调用地址。
可是,C++并没有对指针指向的对象加以不论什么的限制。你不知道这种方法会返回什么,不知道这种方法要接收多少个參数,也不知道接收的參数又是什么类型,而且在C++中。指针还能够參与运算。因此,对于调用者而言,除了看到一个地址。其余一概不知道。一切要等到调用以后才真相大白。这种指针经常被一些不轨之人所利用,让方法指针指向一个破坏系统的方法。就好比给你一把钥匙,让你打开一个盒子。盒子里面是什么?或许是蛋糕。或许那就是潘多拉之盒。
因为方法指针不完好。C#针对这一现象进行了改进——托付。托付的作用与方法指针一样,用它来指向一个方法。而且提供给客户程序调用。
但这种方法指针是有限制的,它规定好了所指向方法的返回值、參数个数以及各个參数的类型。因此。这把“钥匙”能打开蛋糕盒却打不开潘多拉之盒,感觉安全多了。
二、对“托付与事件”的理解
托付是对函数的封装能够当作给方法的特征指定一个名称。
方法是将类型參数化。所谓类型參数化就是说该方法接受一个參数,而该參数是某种类型的參数,比方int、string等等。而托付是将方法參数化。也就是将方法作为一个參数传到一个托付中。
托付是一种引用方法的类型,一旦为托付分配了方法,托付将与该方法具有全然同样的行为。托付用keyworddelegate来声明。事件是说在发生其它类或对象关注的事情时,类或对象可通过事件通知它们,事件对象用keywordevent来声明。
一个托付能够搭载多个方法。这些方法不须要属于同一个类。但必须具有同样的參数列表和返回值类型,被搭载的全部方法被依次唤醒。
托付与事件的协同合作,使得两个须要存在调用关系的类型。在各自的实现中不必编写实际的调用代码,它们仅仅是通过一个事件和一个第三方的托付类型完毕了消息的传递过程。这样两个类型之间不存在不论什么的紧密耦合。实现了“高聚合”和“低耦合”。
三、用事实说话
1.需求:
有一仅仅Tom猫。每当他叫“喵,我是Tom.”的时候。两仅仅小老鼠Jack和Dam就会说“猫来了,快跑吧!”。
2.分析:
该样例涉及两个类,Cat和Mouse。在Main函数中,当Cat的Shout方法触发时,Mouse就运行Run方法。怎样让这两个方法相关联呢。在这里就要用到托付和事件了。
3.实现:
class Cat { private string name; public Cat(string name) { this.name = name; } //声明托付CatShoutEventHandler public delegate void CatShoutEventHandler(); //声明事件Catshout,它的事件类型是托付CatShoutEventHandler public event CatShoutEventHandler CatShout; //猫叫的方法 public void Shout() { Console.WriteLine("喵喵,我是{0}。
", name); //当运行Shout方法时,若CatShout中有对象登记事件,则运行 if (CatShout != null) { CatShout(); } } }
class Mouse
{
public string name;
public Mouse(string name)
{
this.name = name;
}
//老鼠逃跑的方法
public void Run()
{
Console.WriteLine("老猫来了,{0}快跑!", name);
}
}
static void Main(string[] args)
{
Cat cat = new Cat("Tom");
Mouse mouse1 = new Mouse("Jack");
Mouse mouse2 = new Mouse("Dam");
//将mouse的run方法通过实例化托付登记到事件catshout中
cat.CatShout += new Cat.CatShoutEventHandler(mouse1.Run);
cat.CatShout += new Cat.CatShoutEventHandler(mouse2.Run);
cat.Shout();
Console.Read();
}
说明:
"+="添加托付实例对象的意思。实例化托付有两种方法:
(1)直接将方法赋值[=]或者用“+=”给一个托付==>托付名 =[+=] 方法名
(2)托付本质也是一个类,仅仅是一个特殊的类,所以我们也能够实例化一个托付对象通过托付构造函数来注冊托付==》托付名对象名= new 托付名(方法名)
"-="移除托付。(以上使用无參数的托付事件,还能够加入參数)
4.效果:
5.理解:
学习要简单化。说实话托付和事件确实挺难理解的。我如今理解得还非常肤浅。通过这个样例,我们能够这样觉得。CatShoutEventHandler托付将方法CatShout和老鼠的Run联系在一起,当cat发生shout时。触发mouse发生run。使用托付分三步。定义、实例化、调用。学习是个循序渐进的过程。暂且这样理解吧。
欢迎大家评论交流。