一、委托概念
1、概念:Delegate(委托、代理…):委托其实一种程序特性,它特的特点就在于,委托是用来表示方法的。换句话说委托是方法的代表、方法的指针。
int age=10;age其实就是10的代表。
Course myCourse = new Course(); myCourse是一个特定对象的代表。
委托类型 委托变量=具体方法(可以是1个,也可以是多个)。委托就方法的变量。
2、为什么要使用委托?
生活中想象一下,比如我们做一件事情,但是我们自己无法直接去完成。但是我们通过别人可以帮我们完成。
我--->其他人(委托)--->做事情
通过刚才的比较,我们发现,前面age、myCourse等代表的都是某种“静态数据”。
委托代表的是“行为”,就是方法。
软件开发中,我们也会遇到类似情况,那就是我们本身想调用一个行为(方法)但是这个方法因为再不同的对象中,
我们可能直接调用不了,这时候就可以使用委托。
正常情况下:A对象中,创建了B对象,这时候,如果B对象中有一个公共行为C,那么我们在A中是能调用的。
class A
{
B b=new B();
void MyMethod()
{
b.C();
}
void NewMethod(){}
}
问题:如果B想调用A中的行为NewMethod是否可以?当然不行!但是通过委托是可以的。
二、委托的基本使用
- 声明委托(定义方法的原型:方法的返回值类型、方法的参数类型和个数)
2.根据委托编写具体方法
-
创建委托变量(委托是引用类型)
-
将委托变量和一个或多个符合委托定义的具体的方法关联。
-
通过委托变量使用具体的方法(不是直接使用方法)
结论:通过委托变量,可以轻松的调用它所关联的具体方法。
扩展:如果我们给委托变量,同时关联了多个方法,当我们使用委托变量的时候,方法会按照你关联的顺序依次调用。
以上就是我们常说的“多路委托或叫做多播委托”。
好处:我们不仅能动态的增加委托对方法的关联,还可以动态的移除方法的关联。
三、委托的实战应用(一):在多窗体通信中的使用
1、在主窗体A中,创建了若干子窗体B的对象。
现在B窗体需要调用A中的一个方法。正常情况是不行的。但是可以通过委托实现。
2、提示:我们使用委托完成任务的时候,委托变量在哪里定义的技巧是:在哪里使用,就在哪里定义!(谁使用谁创建)
委托变量和具体方法的关联,通常是分开的。一般就是在具体方法定义的地方,进行关联。
总结: B1->A B2->A B3->A
扩展:通过委托如何实现消息的广播?
在哪里接收消息,就把接收消息的方法写到哪里!这里是B窗体。
四、委托的实战应用(二):解决在容器嵌入窗体时的切换问题
五、事件Event(和委托比较)
随便找一个: this.btnCreateChildForm.Click += new System.EventHandler(this.btnCreateChildForm_Click);
public event EventHandler Click
public delegate void EventHandler(object sender, EventArgs e);
通过观察按钮的事件,发现了事件其实是委托的进一步包装。
定义事件:(直接看代码)案例中,我们实现和前面一样的功能,但是这次通过事件来实现。
事件概念:事件其实是对象对外界信息的刺激,产生的一种消息响应机制。
本质:事件其实是委托的进一步包装。
事件的参与者:
【1】发送者(sender):就是对象本身,当时本身信息状态变化的时候,触发一个事件,并通知所有的接受者接收。
passMsgEvent(this.txtSendMsg.Text, this.Text);
【2】接受者(Receiver):就是事件的处理者,在事件发送者触发后,会自动执行的这段代码。
private void ReceiveMsg(string msg, string childName)
{
this.txtContent.Text += $"来自:{childName} 的消息:{msg}\r\n";
}
事件和委托对比不同点:
第一、事件无法直接赋值,比如事件=null;会出现编译错误,而委托可以。
好处:避免用户对事件直接操作,比如Click事件,如果允许Click=null,会把底层代码清除!可以起到保护。
委托相对太“开放”。
第二、event对象没有invoke()方法,只能通过使用括号的方式来运行。
委托和事件的选择:
第一、正常解决问题,你使用委托和事件没有什么本质区别。所以,我们建议是使用委托。
第二、如果我们做控件二次开发,扩展控件的事件的时候,那必须用事件。