你的位置:首页 > ASP.net教程

[ASP.net教程][.net 面向对象编程基础] 委托


[.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);

 定义委托基本上是定义一个新类,所以可以在定义类的任何地方定义委托,既可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在命名空间中把委托定义为顶层对象。根据定义的可见性,可以在委托定义上添加一般的访问修饰符:public、private、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 Dog15   {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 Sheep27   {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 Checken39   {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 Dog21   {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 Sheep37   {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 Chicken54   {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

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