首先让我们先了解一下什么是回调函数
回调函数
1、什么是回调函数?
答:简单的说,回调函数是一个通过函数指针调用的函数。
2、为什么我们要使用回调函数?
答:调用者(Button类)并不关心被调用者是谁;它所知道的是具有特定原型的被调用者(定义在主程序中的MyBtnClick方法)以及一些可能的限制(比如,返回值可以是整数,不过特定的值有特定含义)
举例:
如 果你想知道实践中回调函数多有用,想象一下你想写一个排序算法实现的库(的确很经典),比如冒泡排序,希尔排序,shake排序,快速排序等等。关注点在 于为了是你的库更加通用,你不想嵌入排序逻辑(一个数组内两个元素之间哪一个在前)到你的函数中。你想让客户决定哪一种逻辑。或者说,你想让库对各种数据 类型都有用(int,floats,strings) 等等。因此,你应该怎样做?你会使用函数指针并且利用回调。
总结:就是你写的函数让系统来调用
委托+事件
在系统事件中,如鼠标或键盘按下,发送器就是.NET运行库(假设点了Button一下,那发送器就是Button类).注意,事件的发送器并不知道接收器是谁,这就使得事件非常用用.
事件可以使用多播委托,但是不能保证调用方法的前后顺序.
事件处理方法不能有返回值.只要使用EventHandler委托就必须使用object和EventArtgs参数. object是引发事件的对象, EventArtgs包含有关事件的有用的信息.
事件定义:
事件触发者(如Button类)定义了一个函数指针(如下例中的委托myClick),这个函数指针可以在以后指向某个处理事件函数.当事件发生时,调用该函数指针指向处理函数,并将事件的上下文作为参数传入.处理完成后,控制权将被事件触发者回收.
自我理解:
问:为什么事件要用委托实现?
答:就拿一个标准Button来说,当你点下去之后,会发生的内容在哪儿定义?如果你进入到Button类里定义,好,Button已经被比尔这家伙封装了,你可进不去,进去了也不能修改;咋办昵?????算了,Button哭着对主程序(假设当前主程序是一个Win Form)说,你做我的代理,帮我完成吧.由此,Button将它的Click事件委托给了主程序.这下你可以在Form里为所欲为了,让它干什么,它就得干什么?(Button:"主程序,你是禽兽..."; 主程序:"哇哈哈哈,这可由不得你啦...(屏幕漆黑中...)")
网友理解:
1、委托就是代理.如果你是厂商,假如要你直接去卖你的产品,那你将面对的是所有的消费者.假如你依靠代理卖你的产品,那你将面对的仅仅是各个省或地区的代理。
2、委托是一种特殊的类型(class),用途是来实现对一种方法的封装,在某种事件发生时,自动调用该方法。好处显然易见,它使用户可以自定义自己的方法实现(就是前面所说的为所欲为),通过封装,CLR会在相应事件激发时调用你定义的方法,实现你的功能。
3、 认为是函数指针的是C/C++程序员,理解基本正确,但有一点,委托可以是"成员函数的指针"。认为是类的,没错,.NET里什么都是类,委托类包含了一 个对象(o)和对象中一个方法(m)的信息,实现了调用这个方法(o.m())的方法(委托的调用)。说用委托来实现类的组合,这个观点不敢苟同。类的组 合应该是两个完整的类,如果通过委托把一个类的部分方法和其它类组合应该是不完全的。
using System;
using System.Collections.Generic;
public class MyClass
{
public static void Main()
{
MyClass mc = new MyClass();
myButton godBtn = new myButton();
godBtn.myClick += new EventHandler(mc.godBtnClick);
godBtn.OnmyClick();
Console.ReadLine();
}
public void godBtnClick(object sender,EventArgs e)
{
Console.WriteLine("on my god...button");
}
}
public class myButton
{
public event EventHandler myClick; //一个委托事件 myClick
protected void OnmyClick() //注意,最好使用protected修饰符,以便只给继承它的类使用
{
if(myClick != null)
{
myClick(this,new EventArgs());
}
}
}
using System.Collections.Generic;
public class MyClass
{
public static void Main()
{
MyClass mc = new MyClass();
myButton godBtn = new myButton();
godBtn.myClick += new EventHandler(mc.godBtnClick);
godBtn.OnmyClick();
Console.ReadLine();
}
public void godBtnClick(object sender,EventArgs e)
{
Console.WriteLine("on my god...button");
}
}
public class myButton
{
public event EventHandler myClick; //一个委托事件 myClick
protected void OnmyClick() //注意,最好使用protected修饰符,以便只给继承它的类使用
{
if(myClick != null)
{
myClick(this,new EventArgs());
}
}
}
定义实现一个事件的流程
1、引发事件的对象称事件源;
2、事件总是委托类型的,这个委托类型的签名定义了处理该事件的方法的签名;(如myClick)
3、定义事件处理程序方法的对象称事件接收方(就是主程序此例为MyClass);
4、事件接收方提供的事件处理方法必须与该事件预订的方法签名一致. (如godBtnClick)
5、在事件的通信中,事件发送者不知道哪个对象或方法将要去接收/发送事件,因而在事件源和事件接收者之间就需要一个中间人-委托;
6、当指派多个处理程序给一个事件的时候,处理程序的调用次序是没有保证的.(多播委托)
7、EventHandler 是一个用于事件的委托,它有两个参数object和EventArg,object代表了事件的发送者,EventArg对象代表了事件包含的数据;
8、所以有事件处理方法都可以使用EventHandler,但你也可以使用EventHandler的子类.(如public event PaintEventHandler Paint; 其实PaintEventHandler 是EventHandler的子类)
1)定义事件(变量) public event EventHandler myClick;
2)定义事件方法 public static void godBtnClick(object sender, EventArgs e);
3)将事件与事件方法相关联 mc.myClick+= new EventHandler(godBtnClick); //EventHandler是一个委托,委托通常把方法当参数传递,btnGetClick是一个方法
4)定义响应函数 publicvoid OnmyClick()
5)调用响应函数,响应函数调用触发函数,事件被触发了 mc.OnmyClick();
注:在系统定义的响应事件中,第4) 5)步是不可见的.