委托的概念

16.1委托

     有时我们需要将一个函数作为另一个函数的参数,这时就要用到委托(Delegate)机制。委托是一个较难讲清楚的概念,笔者苦思数日,终于想出了一个巧妙的例子。

作者:梁斌玉 摘自《C#初学课堂》即将出版
BeginnerClassroom@163.com
http://www.cnblogs.com/BeginnerClassroom

       下面我们设计一个马戏表演函数RunCircus(),它的第一个参数是代表动物的函数,传给它什么样的动物,就进行什么动物的表演。请新建一个名为“Delegate”的项目,然后添加如下代码。 

试一试:定义委托 

Code
         // 摘自《C#初学课堂》 http://www.cnblogs.com/BeginnerClassroom
        
// 函数:狗表演
         static   void  DogAct( string  name)
        {
            Console.WriteLine(
" Hello,I am  "   +  name  +   " ! " );
            Console.WriteLine(
@"
                    .----.
                 _.'__    `.
             .--(#)(##)---/#/
           .' @          /###/
           :         ,   #####
            `-..__.-' _.-/###/
                  `;_:    `''
                .'''''''`.
               /,Snoopy ,/
              //  COOL!  //
              `-._______.-'
              ___`. | .'___
             (______|______)
" );

        }

        
// 函数:猫表演
         static   void  CatAct( string  name)
        {
            Console.WriteLine(
" Hello,I am  "   +  name  +   " ! " );
            Console.WriteLine(
@"
              .-. __ _ .-.
               |  `  / /  |
               /     '.()--/
              |         '._/
             _| O   _   O |_
             =/    '-'    /=
               '-._____.-'
               /`//___//`/
              ///o     o///
             (_|         |_)
               |____,____|
               (____|____)
" );

        }

        
// 函数:狮子表演
         static   void  LionAct( string  name)
        {
            Console.WriteLine(
" Hello,I am  "   +  name  +   " ! " );
            Console.WriteLine(
@"
                      ,%%%%%%%%,
                     ,%%//%%%%//%%
                    ,%%%/c "" J/%%%
          %.       %%%%/ o  o /%%%
          `%%.     %%%%    _  |%%%
            `%%     `%%%%(__Y__)%%'
            //       ;%%%%`/-/%%%'
           ((       /  `%%%%%%%'
            //    .'          |
             //  /       /  | |
              ///         ) | |
               /         /_ | |__
               (___________)))))))
" );

        }

        
// 定义委托
         delegate   void  AnimalAct( string  name);

        
// 函数:马戏表演(第一个参数为AnimalAct型委托)
         static   void  RunCircus(AnimalAct animalAct,  string  name)
        {
            animalAct(name);
        }

        
static   void  Main( string [] args)
        {
            
// 把函数DogAct()转换为AnimalAct型委托
            AnimalAct deleDogAct  =   new  AnimalAct(DogAct);
            
// 把委托deleDogAct传给函数RunCircus()
            RunCircus(deleDogAct,  " Snoopy " );

            
// 把函数CatAct()转换为AnimalAct型委托,并传给函数RunCircus()
            RunCircus( new  AnimalAct(CatAct),  "  Kitty  " );

        }

 

   运行结果如下:

            7.JPG

《C#初学课堂》     

  函数 RunCircus(AnimalAct animalAct, string name)的第一个参数实际上是一个代表动物的函数,传给它什么样的函数,它就用什么样的动物进行表演。但为了进行严格的类型检查,我们不能直接把函数的 名称传递给它,而应先定义一个委托(Dlelegate),即定义一种“函数类型”。

 

8.JPG

       委托用关键字delegate声明,上面的语句定义了一种名为AnimalAct的委托(函数类型),明确规定了委托的参数类型和返回值类型。当我们需要把某个函数作为参数时,就要先把它转换为委托实例。

9.JPG

 

   然后把这个委托实例以参数的形式传递给调用它的函数。


13.JPG

  由此可以看出委托实例deleDogAct实际上是函数DogAct()的别名,显然委托和被委托函数应具有相同的参数类型和返回类型。

      在我们的程序中,马戏团总是调用函数RunCircus()进行表演。定义函数RunCircus()时,我们不知道也不关心传递给它的委托代表哪个函 数,直到调用RunCircus()函数,并把实际参数传递给它时,这个函数才具体化。传给它什么样的实际参数,就进行什么样的表演,传给它 deleDogAct委托,马戏团就进行狗的表演;传给它deleCatAct委托,马戏团就进行猫的表演;传给它deleLionAct委托,马戏团就 进行狮子表演。因此以委托为参数的函数具有一定的通用性。

 

下面我们利用委托的通用性设计一个通用的求定积分的函数。

111.JPG

数得形式传递给定积分函数,所以需要利用委托实现。

    请新建一个名为“Integral”的项目,然后添加如下代码。   

试一试:求定积分

Code
       // 摘自《C#初学课堂》 http://www.cnblogs.com/BeginnerClassroom
      
// 被积函数 
         static   double  F1( double  x)
        {
            
return   2 * x + 1 ;
        }

        
// 被积函数 
         static   double  F2( double  x)
        {
            
return  x  *  x ;
        }


       
// 被积函数的委托
         delegate   double  Integrand( double  x);

        
// 函数:定积分
         static   double  DefiniteIntegrate( double  a,  double  b, Integrand f)
        {
            
const   int  sect  =   1000 ;          // 分割数目
             double  delta  =  (b  -  a)  /  sect;
            
double  area  =   0 ;

            
for  ( int  i  =   1 ; i  <=   1000 ; i ++ )
            {
                area 
+=  delta  *  f(a  +  i  *  delta);
            }

            
return  area;
        }

        
// 进行定积分运算
         static   void  Main( string [] args)
        {
            Integrand f1 
=   new  Integrand(F1);
            Integrand f2 
=   new  Integrand(F2);

            
double  result1  =  DefiniteIntegrate( 1 5 , f1);
            
double  result2  =  DefiniteIntegrate( 0 1 , f2);

            Console.WriteLine(
" result1 = {0} " , result1);
            Console.WriteLine(
" result2 = {0} " , result2);
        }

 

 

12.JPG

                                                     《C#初学课堂》

       只需传给定积分函数DefiniteIntegrate()相应的被积函数,就可计算出任何函数的定积分。

       综上所述,利用委托可以实现以函数为参数,提高程序的通用性。委托用关键字的delegate声明,实际上创建一种委托相当于创建一个从 System.Delegate派生出来的类,类中有一个调用列表,列表中包含着被委托函数的引用。与C++的函数指针相比,委托是一种类型安全的方式。

 [转贴请注明出处]
作者:梁斌玉 摘自《C#初学课堂》即将出版 
BeginnerClassroom@163.com  
http://www.cnblogs.com/BeginnerClassroom

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值