C# 代理/委托 Delegate

本文转载自努力,努力,努力
1 . 委托的定义:
委托是函数的封装,它代表一 " 类 " 函数.
他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数的 " 类 " .此时,委托的实例将代表一个具体的函数.
委托声明和定义了一个引用类型,它用来封装方法,用指定的签名来封装方法.一个委托的实例,可以封装静态或者实例方法.
委托是一种引用的类型,一旦为委托分配了方法,委托将与该方法完全相同的行为,委托方法的使用可以像其他任何方法一样, 具有参数和返回值
    委托的一个特征是它们的类型是安全的.可以确保被调用的方法签名是正确的,但他们并不关心调用该方法的是什么类型的对象,甚至不考虑该方法是静态方法还是实例方法.(给定委托的实例可以表示任何类型的任何对象上的实例方法或静态方法,只要方法的签名匹配于委托的签名就可以).

2 . 委托的使用:
    当要把方法传递给其他方法时,需要使用委托.
为什么什么用委托:
        更加灵活的方法调用.

        用于异步回调.

       多线程编程中使用委托来定启动一个线程时调用的方法.

       C#中的事件模型,用他们来指明处理给定事件的方法.

例:

class  Program

{

         // 定义委托

         delegate   double  ProcessDelegate( double  param1,  double  param2);

         static   double  Multiply( double  param1,  double  param2)

        {

             return  param1  *  param2;

        }

         static   double  Divide( double  param1,  double  param2)

        {

             return  param1  /  param2;

    }

         static   void  Main( string [] args)

        {

             // 定义委托变量

            ProcessDelegate pd;

             double  param1  =   20 ;

             double  param2  =   10 ;

            Console.WriteLine( " Enter M to multiply or D to divide " );

             string  input  =  Console.ReadLine();

             if  (input  ==   " M " )

            {

                 // 初始化委托变量,要把一个函数引用赋给委托变量,

                 // 参数是要使用的函数名,且不带括号.

                pd  =   new  ProcessDelegate(Multiply);

            }

             else

            {

                pd  =   new  ProcessDelegate(Divide);

            }

             // 使用该委托调用所选函数

            Console.WriteLine( " Result: {0} " ,pd(param1,param2));

            Console.ReadKey();

}

3 . 多播委托: 引用多个方法的委托,它连续调用每个方法.


为了把委托的单个实例合并为一个多播委托,委托必须是同类型的,返回类型必须是void,不能带输出参数out(可以带引用参数ref).


多播委托应用于事件模型中.


// 声明委托

     public   delegate   void  myDelegate();

     public   partial   class  Form1 : Form

    {

         public  Form1()

        {

            InitializeComponent();

        }

         public   void  aa()

        {

            Console.WriteLine( " aa " );

        }

         public   void  bb()

        {

            Console.WriteLine( " bb " );

        }

         public   void  cc()

        {

            Console.WriteLine( " cc " );

        }


        myDelegate md;


         private   void  button1_Click( object  sender, EventArgs e)

        {

            md  =   new  myDelegate(aa);

            md  +=   new  myDelegate(bb);

            myDelegate m  =   new  myDelegate(cc);

            md  +=  m ;

            md();

        }

    }



4 . 异步回调:

由于实例化委托是一个对象,所以可以将其作为参数进行传递.也可以将其赋值给属性.这样,方法便可以将一个委托作为参数来接受,并且以后可以调用该委托.这样称为异步回调,是在较长的进程完成后用来通知调用方的常用方法.以这种方式使用委托时,使用委托的代码无需了解有关所用方法的实现方面的任何信息.


回调的另一个常见用法是定义自定义的比较方法并将该委托传递给排序方法.


    例:

// 定义委托

     delegate   void  Del( int  a, int  b);

     class  Program

    {

         static   void  Main( string [] args)

        {

            Program p  =   new  Program();

            Del d  =   new  Del(p.F_min);    // 实例化委托并传给他比较的方法.

            p.CallBack( 10 ,  30 , d);    // 调用回调函数

        }


         // 回调函数,将委托实例作为方法参数进行传递.

    public   void  CallBack( int  a, int  b,Del d)

       {

           d(a, b);  // 执行委托

        }

        // 输出较大的数

         public   void  F_max( int  a,  int  b)

        {

            Console.WriteLine( " 大的那个数为:  "   +  Math.Max(a,b));       

        }
// 输出较小的数

      }

5 . 匿名方法

    匿名方法允许我们以一种”内联”的方式来编写方法代码,将代码直接与委托实例相关联,从而使得委托实例化的工作更加直观和方便.

使用例子:

class  Program{

     // 定义委托

     public   delegate   string  dTest( string  val);

     static   void  Main( string [] args){

         string  mid  =   " 男子足球队 " ;

         // 匿名方法

        dTest aDelegate  =   delegate ( string  param){

            param  +=  mid;

            param  +=   " 加油. " ;

             return  param;

        };

        Console.WriteLine(aDelegate( " 中国 " ));

        Console.ReadLine();

    }

}

如果委托类型的返回类型为void,匿名方法里便不能返回任何值.如果不为void,匿名方法里返回的值必须和委托类型的返回值兼容.

6 . 何时使用委托,何时接口 ?

   委托:

    当使用事件设计模式时.

    当封装静态方法可取时.

    当调用方不需要访问实现该方法的对象中的其他属性方法或接口时.

    需要方便的组合.

    当类可能需要该方法的多个实现时.

   接口:

    当存在一组可能被调用的相关方法时.

    当类只需要方法的单个实现时.

    当使用接口的类想要将该接口强制转换为其他接口或类类型时.


         public   void  F_min( int  a,  int  b)

        {

            Console.WriteLine( " 小的那个数为:  "   + Math.Min(a,b));

        }
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值