码迷,mamicode.com
首页 > Web开发 > 详细

[.net 面向对象编程基础] (21) 委托

时间:2015-06-16 07:51:56      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:

[.net 面向对象编程基础] (20)  委托

   上节在讲到LINQ的匿名方法中说到了委托,不过比较简单,没了解清楚没关系,这节中会详细说明委托。

1.什么是委托?

学习委托,我想说,学会了就感觉简单的不能再简单了,没学过或都不愿了解的人,看着就头大,其实很简单。委托在.net面向对象编程和学习设计模式中非常重要,是学习.net面向对象编程必须要学会并掌握的。

委托从字面上理解,就是把做一些事情交给别人来帮忙完成。在C#中也可以这样理解,委托就是动态调用方法。这样说明,就很好理解了。

平时我们会遇到这样的例子需要处理,比如有一个动物园(Zoo)(我还是以前面的动物来说吧)里面有狗(Dog)、鸡(Chicken)、羊(Sheep)……,也许还会再进来一些新品种。参观动物员的人想听动物叫声,那么可以让管理员协助(动物只听懂管理员的),这样就是一个委托的例子。

在实现委托之前,我们先看一下委托的定义:

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

委托(delegate),有些书上叫代理或代表,都是一个意思,为了避免了另一个概念代理(Proxy)混淆,还是叫委托更好一些。

学过c++的人很熟悉指针,C#中没有了指针,使用了委托,不同的是,委托是一个安全的类型,也是面向对象的。

2.委托的使用

委托(delegate)的声明的语法如下:

    public delegate void Del(string parameter);

 定义委托基本上是定义一个新类,所以可以在定义类的任何地方定义委托,既可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在命名空间中把委托定义为顶层对象。根据定义的可见性,可以在委托定义上添加一般的访问修饰符:publicprivate、protected等:

实际上,“定义一个委托”是指“定义一个新类”。只是把class换成了delegate而已,委托实现为派生自基类System. Multicast Delegate的类,System.MulticastDelegate又派生自基类System.Delegate。

下面我们使用委托来实现上面动物园的实例,实现如下: 

 1 /// <summary>
 2 /// 动物类
 3 /// </summary>
 4 class Zoo
 5 {
 6     public class Manage
 7     {
 8         public delegate void Shout();   
 9         public static void CallAnimalShout(Shout shout)
10         {
11             shout();
12         }
13     }        
14     public class Dog
15     {
16         string name;
17         public Dog(string name)
18         {
19             this.name = name;
20         }
21         public void DogShout()            {
22 
23             Console.WriteLine("我是小狗:" + this.name + "汪~汪~汪");
24         }            
25     }
26     public class Sheep
27     {
28         string name;
29         public Sheep(string name)
30         {
31             this.name = name;
32         }
33         public void SheepShout()
34         {
35             Console.WriteLine("我是小羊:" + this.name + "咩~咩~咩");
36         }
37     }
38     public class Checken
39     {
40         string name;
41         public Checken(string name)
42         {
43             this.name = name;
44         }
45         public void ChickenShout()
46         {
47             Console.WriteLine("我是小鸡:" + this.name + "喔~喔~喔");
48         }
49     }
50 }

动物园除了各种动物外,还有动物管理员,动物管理员有一个委托。调用如下:            

//参观者委托管理员,让某种动物叫
Zoo.Dog dog=new Zoo.Dog("汪财");
Zoo.Manage.Shout shout = new Zoo.Manage.Shout(dog.DogShout);
//管理员收到委托传达给动物,动物执行主人命令
Zoo.Manage.CallAnimalShout(shout);        

运行结果如下:

技术分享 

上面的实例实现了委托的定义和调用,即间接的调用了动物叫的方法。肯定有人会说,为什么不直接调用小狗叫的方法,而要绕一大圈来使用委托。如果只是简单的让一种动物叫一下,那么用委托确实是绕了一大圈,但是如果我让让狗叫完,再让羊叫,再让鸡叫,反反复复要了好几种动物的叫声,最后到如果要结算费用,谁能知道我消费了多少呢?如果一次让几种动物同时叫呢,我们是不是要再写一个多个动物叫的方法来调用呢?当遇到复杂的调用时委托的作用就体现出来了,下面我们先看一下,如何让多个动物同时叫,就是下面要说的多播委托。

委托需要满足4个条件:

a.声明一个委托类型
b.找到一个跟委托类型具有相同签名的方法(可以是实例方法,也可以是静态方法)
c.通过相同签名的方法来创建一个委托实例
c.通过委托实例的调用完成对方法的调用 

3.多播委托

每个委托都只包含一个方法调用,调用委托的次数与调用方法的次数相同。如果调用多个方法,就需要多次显示调用这个委托。当然委托也可以包含多个方法,这种委托称为多播委托。 

当调用多播委托时,它连续调用每个方法。在调用过程中,委托必须为同类型,返回类型一般为void,这样才能将委托的单个实例合并为一个多播委托。如果委托具有返回值和/或输出参数,它将返回最后调用的方法的返回值和参数。

下面我们看一下,调用“狗,鸡,羊”同时叫的实现:           

//声明委托类型
Zoo.Manage.Shout shout;
//加入狗叫委托
shout = new Zoo.Manage.Shout(new Zoo.Dog("小哈").DogShout);
//加入鸡叫委托
shout += new Zoo.Manage.Shout(new Zoo.Checken("大鹏").ChickenShout);
//加入羊叫委托
shout += new Zoo.Manage.Shout(new Zoo.Sheep("三鹿").SheepShout);
//执行委托
Zoo.Manage.CallAnimalShout(shout);
Console.ReadLine();

运行结果如下:

 技术分享 

上面的示例,如果我们感觉还不足以体现委托的作用。我们假动物除了会叫之外,还有其它特技。狗会表演“捡东西(PickUp)”,羊会踢球(PlayBall),鸡会跳舞(Dance)

观众想看一个集体表演了,让狗叫1次,抢一个东西回来;羊叫1次踢1次球,鸡叫1次跳1只舞。 然后,顺序倒过来再表演一次。如果使用直接调用方法,那么写代码要疯了,顺序执行一次,就顺序写一排方法代码,要反过来表演,又要倒过来写一排方法。这还不算高难度的表演,假如要穿插进行呢?使用委托的面向对象特征,我们实现这些需求很简单。看代码:

首先我们改进一下羊,狗,鸡,让他们有一个特技的方法。

 

 1 /// <summary>
 2 /// 动物类
 3 /// </summary>
 4 class Zoo
 5 {
 6     public class Manage
 7     {
 8         public delegate void del();      
 9 
10         /// <summary>
11         /// 动物表演
12         /// </summary>
13         /// <param name="obj"></param>
14         /// <param name="shout"></param>
15         public static void CallAnimal(del d)
16         {
17             d();
18         }  
19     }
20     public  class Dog
21     {
22         string name;
23         public Dog(string name)
24         {
25             this.name = name;
26         }           
27         public void DogShout()
28         {
29             Console.WriteLine("我是小狗:"+this.name+"汪~汪~汪");
30         }      
31         public void PickUp()
32         {
33             Console.WriteLine("小狗" + this.name + " 捡东西 回来了");
34         }
35     }
36     public class Sheep
37     {
38         string name;
39         public Sheep(string name)
40         {
41             this.name = name;
42         }
43         public void SheepShout()
44         {
45             Console.WriteLine( "我是小羊:"+this.name+" 咩~咩~咩 ");
46         }
47         public void PlayBall() 
48         {
49             Console.WriteLine("小羊" + this.name + " 打球 结束了");
50         }
51     }
52 
53     public class Chicken
54     {
55             string name;
56             public Chicken(string name)
57         {
58             this.name = name;
59         }
60         public void ChickenShout()
61         {
62             Console.WriteLine("我是小鸡:"+this.name+"喔~喔~喔");
63         }
64         public void Dance()
65         {
66             Console.WriteLine("小鸡" + this.name + " 跳舞 完毕");
67         }
68     }
69 }

 调用如下: 

 1 //多播委托(二)动物狂欢
 2 
 3 //挑选三个表演的动物
 4 Zoo.Dog dog = new Zoo.Dog("小哈");
 5 Zoo.Chicken chicken = new Zoo.Chicken("大鹏");
 6 Zoo.Sheep sheep = new Zoo.Sheep("三鹿");
 7 
 8 //加入狗叫委托
 9 Zoo.Manage.del dogShout = dog.DogShout;
10 //加入鸡叫委托
11 Zoo.Manage.del chickenShout = chicken.ChickenShout;
12 //加入羊叫委托
13 Zoo.Manage.del sheepnShout = sheep.SheepShout;
14 
15 //加入狗表演
16 Zoo.Manage.del dogShow = new Zoo.Manage.del(dog.PickUp);
17 ;  //加入鸡表演
18 Zoo.Manage.del chickenShow = new Zoo.Manage.del(chicken.Dance);
19 //加入羊表演
20 Zoo.Manage.del sheepShow = new Zoo.Manage.del(sheep.PlayBall);
21 
22 
23 //构造表演模式
24 //第一种表演方式:狗叫1次抢一个东西回来;羊叫1次踢1次球;鸡叫1次跳1只舞;
25 Zoo.Manage.del del = dogShout + dogShow + chickenShout + chickenShow + sheepnShout + sheepShow;
26 //执行委托
27 Zoo.Manage.CallAnimal(del);
28 
29 
30 Console.WriteLine("\n第二种表演,顺序反转\n");
31 //第二种表演,顺序反转
32 var del2 = del.GetInvocationList().Reverse();
33 //执行委托
34 foreach (Zoo.Manage.del d in del2)           
35 Zoo.Manage.CallAnimal(d);
36 Console.ReadLine();

运行结果如下:

 技术分享

 <明天继续。。。。未完> 

 ============================================================================================== 

返回目录

 <如果对你有帮助,记得点一下推荐哦,有不明白的地方或写的不对的地方,请多交流>
 

QQ群:467189533

==============================================================================================  

[.net 面向对象编程基础] (21) 委托

标签:

原文地址:http://www.cnblogs.com/yubinfeng/p/4579664.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!