• 关于C#委托


      前段时间闲来无事,随便在网上逛,谁知一不小心看到了这篇文章。感觉有必要了解下所以就转了下来一块分享下。。

      1.委托概述 
    委托是C#中新加入的一个类型,可以把它想作一个和Class类似的一种类型,和使用类相似,使用一个委托时,需要两个步骤,首先你要定义一个委托,就像是定义一个类一样;然后,你可以创建一个或多个该委托的实例。 
    定义一个委托的语法是这样的: 
    [public/protected/private] delegate returnType delegateName(paramtype param1,…) 
    这是我自己写的,看起来好像有点怪怪的,我来解释一下,private/protected/private是限定词,就不多说了,delegate是申 明一个委托的关键词,returnType是一个返回类型,delegateName是一个你给委托起的名字,你可以写任何一个你喜欢的名 字,paramtype param1…这个是参数列表。说了这么多可能看起来还是不是很好理解,我是这样认为的,实用点来讲,委托定义就是在一个函数定义中间加入一个 delegate的关键词。它的作用类似于你申明一个类: 
    public class ClassName {…} 
    创建一个委托的实例: 
    [public/protected/private] delegateName deleInstanceName = new delegateName(MethodName) 
    这个类似于实例化一个类,public ClassName instancename = new ClassName(…),这里有个要注意的地方,即MethodName方法要和delegateName的签名一致。什么是签名一致,就是说 MethodName的参数列表,返回值要分别和returnType、(paramtype param1,…)一致。举个例子来说明下: 
    public delegate string DelegateDemo(string name, int age); 
    比如我们如上定义了一个委托,就写法来说,其实就是在函数 string DelegateDemo(string name, int age)前面加了一个delegate的关键字,下面我们来用创建一个函数: 
    public string AgentDemo(string name, int age) 
    { 
    string rev = “”; 
     
    return rev; 
    } 
    这个函数是做参数传递给一个DelegateDemo实例的,接下来创建一个DelegateDemo的实例: 
    DelegateName instanceDemo = new DelegateName(AgentDemo); 
    这时要说到一致了,即AgentDemo和声明委托时的DelegateDemo(我们姑且将delegate去掉)这两个函数的返回值,参数列表要相同。终于说完了,不知道看的人明不明白。 
    接下来,我们可以使用这个委托了(调用一个委托),如下: 
    string name = “cshape”; 
    int age = 20; 
    instanceDemo(name, age); 
    当instanceDemo执行时,会执行AgentDemo函数,instanceDemo相当于C里的一个函数指针,现在这个指针指向AgentDemo的函数入口地址。 
    2.多点委托 
    前面提到的委托都只包含对一个方法的调用,如果需要调用多个方法,需要多次显示的调用这个委托,我们还有另的选择,我们可以让一个委托中包含多个方法,这样我们一次显示调用委托,就可以按照顺序连续的调用多个方法。看下面的例子: 
    public delegate void MultiDelegate(string name); 
    public void AgentDemo1(string str) 
    { 
    Console.WriteLine(str + “this is AgentDemo1\n”); 
    } 

    public void AgentDemo2(string s) 
    { 
    Console.WriteLine(s + “this is AgentDemo2\n”); 
    } 

    MultiDelegate multiDemo = new MultiDelegate(AgentDemo1); 
    multiDemo += new MultiDelegate(AgentDemo2); 
    multiDemo(“multiDemo test :”); 

    输出的结果应该是: 
    multiDemo test :this is AgentDemo1 
    mutliDemo test :this is AgentDemo2 

    可以看到我们一次显示的调用一个委托,它顺序的(按照你添加方法的顺序)执行了方法AgentDemo1和AgentDemo2。这里要注意的有几点: 
    ● 委托支持 +=,-=这样的运算符,对应为添加或去掉一个方法 
    ● 多点委托不可以定义有返回值,因为无法处理多个方法的返回值,所以如果要使用多点委托,应该用void,否则你的编译会返回一个错误 
    ● 多点委托不建议你的参数列表中有OUT的类型,这样只会out最后一个方法的值,其他的值会丢失。 
    3.委托的理解 
    首先申明,这只是我举的一个例子,目的是帮助理解委托的过程,其中很多地方都经不起推敲,望大家知悉。言归正传,
    你想要吃饭, 
    但是自己又不会做(委托方不知道实现细节), 
    你计划找个饭店,叫个回锅肉饭(定义了一个委托) 
    你决定找常去的那家叫做A的饭店(实例化一个委托) 
    你打电话给A饭店(委托调用) 
    A饭店给你做好了你的回锅肉饭(代理函数工作) 
    饭来了,真好。 

    4.委托的使用时机 
    当你需要把一个方法传送给其他方法时,可以考虑使用委托。好像不是很好理解,也可以这样说,当你确定要处理一件事,但又不能确定处理方法时,可以考虑用委托。其实单独的说委托的应用好像有点牵强,委托更多的是在事件中的应用。 
    5.一个委托的例子 
    我用两个类来做这个例子,一个类,我称它为委托方,一个类我称它为代理方,代码如下: 
    using System; 

    namespace Visen.Demo.Delegate 
    { 
    ///<summary> 
    /// StartUp 委托演示中的程序入口,含委托方。 
    ///</summary> 
    class StartUp 
    { 
    #region公用的方法 

    #region应用程序的主入口点。 
    ///<summary> 
    ///应用程序的主入口点。 
    ///</summary> 
    [STAThread] 
    static void Main(string[] args) 
    { 
    Console.WriteLine("This is a delegate demo\n"); 

    Visen.Demo.Delegate.Agent ag = new Agent(); 

    //定义一个委托类型的对象 
    OutMessage singleDele = new OutMessage(ag.ShowMessage); 
    OutMessage deleStaticMeth = new OutMessage(Agent.SShowMessage); 

    //定义一个多点委托 
    OutMessage MultiDele = new OutMessage(ag.ShowMessage); 
    MultiDele += new OutMessage(Agent.SShowMessage); 

    singleDele(" delegate instance singleDele"); 
    deleStaticMeth(" delegate instance deleStaticMeth"); 
    MultiDele(" this is a MultiDele"); 
    Console.Read(); 
    } 
    #endregion应用程序的主入口点。 

    #endregion公用的方法 

    #region私用的字段 
    ///<summary> 
    ///定义一个委托类型 
    ///</summary> 
    private delegate void OutMessage(string msg); 
    #endregion私有的字段 
    } 
    } 

    下面是代理方: 
    using System; 

    namespace Visen.Demo.Delegate 
    { 
    ///<summary> 
    /// Agent 类为委托者的代理方,处理委托者委托的事务。 
    ///</summary> 
    public class Agent 
    { 
    #region公用的方法 

    #region空的构造函数 
    ///<summary> 
    ///空的构造函数 
    ///</summary> 
    public Agent() 
    { 
    } 
    #endregion空的构造函数 

    #region显示一条信息到控制台,一个类成员函数作为代理方 
    ///<summary> 
    ///显示一条信息到控制台,一个类成员函数作为代理方 
    ///</summary> 
    ///<param name="msg">显示内容</param> 
    public void ShowMessage(string msg) 
    { 
    Console.WriteLine("Method ShowMessage out:" + msg + "\n"); 
    } 
    #endregion显示一条信息到控制台,一个类成员函数作为代理方 

    #region显示一条信息到控制台,一个类静态函数作为代理方 
    ///<summary> 
    ///显示一条信息到控制台,一个类静态函数作为代理方 
    ///</summary> 
    ///<param name="msg">显示信息</param> 
    public static void SShowMessage(string msg) 
    { 
    Console.WriteLine("static Method SShowMessage out:" + msg + "\n"); 
    } 
    #endregion显示一条信息到控制台,一个类静态函数作为代理方 

    #endregion公用的方法 
    } 
    } 
    输出为: 
    This is a delegate demo 

    Method ShowMessage out: delegate instance singleDele 

    static Method SShowMessage out: delegate instance deleStaticMeth 

    Method ShowMessage out: this is a MultiDele 

    static Method SShowMessage out: this is a MultiDele 

    可见:方法函数可以是类成员函数,也可以是一个静态成员,只要和委托的签名相同就可以了。 

    有错的地方,请大家批评指正,谢谢!

  • 相关阅读:
    一夜风雨,夏入秋
    Starting,博客园的开通,渐行渐远
    The second day
    The first day study
    [前缀和] Jzoj P3913 艰难的选择
    [树形dp] Jzoj P3914 人品问题
    [匈牙利][Floyd] Jzoj P1015 导弹
    [高精度][规律][二分] Jzoj P4213 对你的爱深不见底
    [概率dp] Jzoj P4212 我想大声告诉你
    [最小割][最大流] 洛谷 P1345 奶牛的电信
  • 原文地址:https://www.cnblogs.com/song_/p/1804386.html
Copyright © 2020-2023  润新知