C#学习笔记(七)
2008-11-17 16:14
225 查看
第七讲 委托1
委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,
委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。
下面的示例声明了一个名为 Del 的委托,该委托可以封装一个采用字符串作为参数并返回 void 的方法。
委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,
委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。
下面的示例声明了一个名为 Del 的委托,该委托可以封装一个采用字符串作为参数并返回 void 的方法。
public delegate void Del(string message); 委托具有以下特点: 委托类似于 C++ 函数指针,但它是类型安全的。 委托允许将方法作为参数进行传递。 委托可用于定义回调方法。 委托可以链接在一起;例如,可以对一个事件调用多个方法。 方法不需要与委托签名精确匹配。有关更多信息,请参见协变和逆变。 C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替 单独定义的方法。 using System; //创建一个类 class MyDelegate { //创建一个静态函数:张三吃东西。 //字符串的参数food static void zsEat(string food) { //在屏幕上打印 Console.WriteLine("张三吃" + food); } static void Main() { //调用 zsEat("西瓜"); } } 这个程序很简单,就是为了打印张三吃食物。大家自己编译执行下,不是很难理解。 结果是张三吃西瓜。下面我们来改下这段程序,通过委托的方法来调用张三吃东西 这个函数。 using System; /// <summary> /// 声明一个EatDelegate这样的委托 /// 委托的声明首先使用了delegate关键字,然后是委托的返回值void,括号里是委托的参数 /// 委托原型必须跟域委托的方法具有相同的返回值和参数(个数也必须一致) /// 域委托的方法就是MeDelegate类下的void zsEat(string food)方法 /// 委托的本质就是一个类,任何可以声明的地方都可以声明委托 /// </summary> /// <param name="food"></param> delegate void EatDelegate(string food); class MyDelegate { static void zsEat(string food) { Console.WriteLine("张三吃" + food); } static void Main() { //下面我们就可以通过调用委托来调用张三吃西瓜这个函数了 //这里声明了一个委托的实例zs并给它初始化 //EatDelegate里面带的参数是我们域代理的函数的名称 //这就意味着zs这个委托实例它所代理的函数的名字叫zsEat,两者之间能联系 EatDelegate zs = new EatDelegate(zsEat); //进行调用使用函数 zs("西瓜"); } } 我们进行执行编译代码,结果和上面是一样的。而这一次我们并没有直接 使用zsEat这个函数,而是通过代理zs来调用它,它们的执行效果都是一样 的。好,接下来张三一个人吃西瓜觉得不过瘾,我们添加李四等人, 代码如下: using System; delegate void EatDelegate(string food); class MyDelegate { static void zsEat(string food) { Console.WriteLine("张三吃" + food); } //添加一个李四吃东西函数 static void lsEat(string food) { Console.WriteLine("李四吃" + food); } //添加一个王五吃东西函数 static void wwEat(string food) { Console.WriteLine("王五吃" + food); } static void Main() { EatDelegate zs = new EatDelegate(zsEat); EatDelegate ls = new EatDelegate(lsEat); EatDelegate ww = new EatDelegate(wwEat); //进行调用使用函数 zs("西瓜"); ls("西瓜"); ww("西瓜"); } } 屏幕上也打印出来了张三,王五,李四都在吃西瓜,没有什么问题。 但是他们都在吃同一样东西西瓜,为什么我们要输入三次呢?这样 不是很麻烦嘛,有没有什么办法可以只输入一次西瓜,而同时都调用 了这3个函数了呢?有的,委托链可以实现这样的功能。这也是委托一 个十分强大的地方,我们修改下代码,声明委托链: using System; delegate void EatDelegate(string food); class MyDelegate { static void zsEat(string food) { Console.WriteLine("张三吃" + food); } static void lsEat(string food) { Console.WriteLine("李四吃" + food); } static void wwEat(string food) { Console.WriteLine("王五吃" + food); } static void Main() { EatDelegate zs = new EatDelegate(zsEat); EatDelegate ls = new EatDelegate(lsEat); EatDelegate ww = new EatDelegate(wwEat); //声明一个委托链,不需要实例化 EatDelegate eatChain; //接下来把张三李四王五都加进这个委托链 eatChain = zs + ls + ww; //现在让他们一起吃西瓜 eatChain("西瓜"); } } 我们保存代码执行,效果如下: 我们看,我们只使用了一次西瓜的参数,就让张三李四王五同 时吃西瓜了。我们回过头来再来看下代码,(eatChain = zs + ls + ww) 在委托链eatChain中,只要把张三李四王五这几个委托的实例加到 这个委托链里面,之后向调用方法一样调用这个委托链eatChain("西瓜"),它就会依次 按照上面加入的顺序去执行这几个委托所对应的函数了。 好,接下来我们把程序变得更具有逻辑性些: using System; delegate void EatDelegate(string food); class MyDelegate { static void zsEat(string food) { Console.WriteLine("张三吃" + food); } static void lsEat(string food) { Console.WriteLine("李四吃" + food); } static void wwEat(string food) { Console.WriteLine("王五吃" + food); } static void Main() { EatDelegate zs = new EatDelegate(zsEat); EatDelegate ls = new EatDelegate(lsEat); EatDelegate ww = new EatDelegate(wwEat); //声明一个委托链,不需要实例化 EatDelegate eatChain; //张三李四王五刚刚放假,非常高兴决定搞一个party Console.WriteLine("张三,李四,王五开座谈会"); //他们三个人都在吃西瓜呀 eatChain = zs + ls + ww; eatChain("西瓜"); //这个时候,李四的电话响了 Console.WriteLine("李四出去接电话"); //李四就吃不了西瓜了 eatChain -= ls; //张三和王五继续吃香蕉 eatChain("香蕉"); //过了一会李四回来了 Console.WriteLine("李四回来了"); eatChain += ls; //他们接着吃桔子 eatChain("桔子"); } } 我们来看下效果: 我们来看一下,前面他们3个人吃西瓜我们都理解了,这个时候李四 出去接电话了.我们用一个"-="将ls这个实例开除出eatChain这个 委托链,接着执行吃香蕉.我们可以在屏幕上看出只有张三和王五在 吃香蕉。这时李四又回来了,李四也要继续吃东西eatChain += ls 把李四又加了进去,接着他们一起吃桔子eatChain("桔子"),我们看 结果他们3个人又都在一起吃桔子了。 C#其实重载了-=和+=这2个操作符来对委托链里的元素进行加减操作,从而使得我们可以随意控制委托链里的元素个数。 static void zsEat(string food) { Console.WriteLine("张三吃" + food); } static void lsEat(string food) { Console.WriteLine("李四吃" + food); } static void wwEat(string food) { Console.WriteLine("王五吃" + food); } 向这样只有几句话的委托方法微软提供了一种非常简单的书写方式给我们,使得我们可以更方便的写出委托,下面我们来修改下代码: using System; delegate void EatDelegate(string food); class MyDelegate { static void Main() { //声明一个委托链,给他赋一个空值 EatDelegate eatChain = null; //三个人都在吃西瓜 eatChain += delegate(string food) { Console.WriteLine("张三吃" + food); }; eatChain += delegate(string food) { Console.WriteLine("李四吃" + food); }; eatChain += delegate(string food) { Console.WriteLine("王五吃" + food); }; eatChain("西瓜"); } } 我们编译执行可以得到张三李四王五都在吃西瓜。虽然我们没有书写 zsEat(string food),lsEat(string food),wwEat(string food) 这些方法,但是呢我们把这些方法直接加到了委托链里面。当委托链执行 的时候,得出了刚才一样的效果(屏幕上3个人吃西瓜)。这个就是C#2.0新 增的匿名方法,它使的我们更加容易的去创建委托,有关匿名方法的讲解 可以去MSDN上的webcast网络讲座上,李建忠老师的《C#2.0锐利体验系 列课程》中的《匿名方法,迭代器》有深入详细的讲解, 若果感兴趣可以去下载学习。
相关文章推荐
- C#学习笔记(一)
- C#学习笔记
- C#学习笔记(二):构造函数的执行序列
- C#学习笔记(十):阴影和深度复制
- C#学习笔记(四):结构类型
- C#学习笔记(十三):读写Txt文件
- C#学习笔记(二十):Windows应用程序安装部署概念
- C#学习笔记系列之二:delegate
- C#学习笔记(十六):使用打开保存文件对话框
- C#学习笔记(2)--.NET 代码编译过程
- c#学习笔记
- C#学习笔记(三)
- C#学习笔记
- C#学习笔记
- c#学习笔记(WinForm篇)
- C#学习笔记(二)
- C#学习笔记
- c#学习笔记
- C#学习笔记(四)中级 类 类的成员属性 只读属性和索引 再说索引
- C#学习笔记(五)(Winform窗体)(一)