转载

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

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

运行结果如下:

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

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

委托需要满足 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();

运行结果如下:

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

上面的示例,如果我们感觉还不足以体现委托的作用。我们假动物除了会叫之外,还有其它特技。狗会表演“捡东西( 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();

运行结果如下:

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

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

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

返回目录

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

QQ群:467189533

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

正文到此结束
Loading...