委托和事件
回调(callback)函数实际上是方法调用的指针,也称为函数指针,是一个非常强大的编程特性。.NET以委托的形式实现了函数指针的概念,.NET委托是类型安全的。
1、委托
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
当要把方法传给其他方法时,需要使用委托。
int i = int.Parse("99");
启动线程—在C#中,可以告诉计算机并行运行某些新执行序列。在基类System.Threading.Thread的一个实例上使用方法Start(),就可以开始执行一个线程。
通用库类—有许多库包含执行各种标准任务的代码。这些库通常可以自我包含。
事件— 一般是通知代码发生了什么事件。GUI编程主要是处理事件。在发生事件时,运行库需要知道应执行哪个方法。这需要把处理事件的方法传送为委托的一个参数。
要启动一个新线程,有一个EntryPoint()的方法,该方法是开始运行线程时的地方。
void EntryPoint()
{
}
也可以用下面的代码开始执行新线程:
Thread NewThread = new Thread();
Thread.Start(EntryPoint);
.1 在C#中声明委托
使用委托两个步骤:先定义要使用的委托,后创建该委托的一个或多个实例。
定义委托语法:delegate void VoidOperation(uint x);
.2 C#中使用委托
在int上调用ToString() 方法的一种相当冗长的方式:
private delegate string GetAString();
static void Main(string[] args)
{
int x = 40;
GetAString firstStringMethod = new GetAString(x.ToString);
Console.WriteLine("String is " + firstStringMethod());
}
委托的一个特征是它们的类型是安全的,可以确保被调用的方法签名是正确的。但它们不关心调用该方法的是什么类型的对象,甚至不考虑该方法是表态方法,还是实例方法。
给定委托的实例可以表示任何类型的任何对象上的实例方法或表态方法—只要方法的签名匹配于委托的签名即可。
匿名方法
想使委托工作,方法必须已经存在(即委托是用方法的签名定义的)。
使用委托还有另外一种方式:即通过匿名方法。匿名方法上用作委托参数的一个代码块。
如何使用匿名方法:
class Program
{
delegate string delegateTest(string val);
static void Main(string[] args)
{
string mid = ",middle part6,";
delegateTest anonDel = delegate(string param)
{
param += mid;
param += " and this was added to the string";
return param;
};
Console.WriteLine(anonDel("Start of string"));
}
}
多播委托
多播委托:委托包含多个方法。
调用多播委托,可以按顺序连续调用多个方法,委托的签名就必须返回void。编译器发现某个委托返回 void,就会自动假定这是一个多播委托。
delegate void DoubleOp(double value);
class MainEntryPoint
{
static void Main()
{
DoubleOp operations = new DoubleOp(MathOperations.MultiplyByTwo);
operations += new DoubleOp(MathOperations.Square);
}
}
多播委托还识别运算符-和-=,在从委托中删除方法调用 。
将方法绑定到委托
语法如下:
static void Main(string[] args)
{
GreetingDelegate delegate1;
delegate1 = EnglishGreeting; // 先给委托类型的变量赋值
delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法
// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法
GreetPeople("Flora", delegate1);
Console.ReadKey();
}
输出为: Morning, Flora 早上好,Flora
委托不同于string的一个特性:可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。
事件
C#事件的目的是为了让用户无需理解底层的委托就可以使用它们。
1、从客户的角度讨论事件
事件接收器是指在发生某些事情时被通知的任何应用程序、对象或组件。
发送器的作用是引发事件,它可以是应用程序中的另一个对象或程序集,在系统事件中,例如鼠标单击或键盘按键,发送器就是.NET运行库。注:事件的发送器并不知道接收器是谁。
使用委托:在事件接收器的某个地方有一个方法,它负责处理事件 。在每次发生已注册的事件时,就执行这个事件处理程序。
发送器定义接收器要使用的委托,接收器将事件处理程序注册到事件中。
连接事件处理程序的过程称为封装事件。
btnOne.Click += new EventHandler(Button_Click);
把第二个按钮的Click事件也连接到同一个Button_Click方法上:
btnOne.Click += new EventHandler(Button_Click);
btnTwo.Click += new EventHandler(Button_Click);
如果使用匿名方法,就不需要Button_Click方法和btnTwo_Click方法了:
btnOne.Click += new EventHandler(lblInfo.Text = "Button One was pressed";);
btnTwo.Click += new EventHandler(lblInfo.Text = "Button Two was pressed";);
btnTwo.Click += new EventHandler(MessageBox.Show("This only happens in Button 2 click event"););