委托是C#最重要的特性之一,C#后面的所有特性基本都是建立在委托的基础上的。

1、C#委托是什么?

可以把C#的委托理解为函数的一个包装,它使得C#中的函数可以作为参数来被传递。如果你学过C++,可以理解为相当于上面的函数指针。

委托的定义和方法的定义类似,只是在定义的前面多了一个delegate关键字。下面就是一个委托的例子:

public delegate void MyDelegate(int para1,string para2);

委托能包装的方法是有一定限制的,例如能被前面的委托类型MyDelegate包装的方法需要满足以下条件:

(1)方法的返回类型必须为void;

(2)方法必须有两个参数,并且第一个参数应为int类型,第二个参数为String类型。

比如:public vodi MyMethod(int a,string b){}

总结一下可以得出:被委托包装的方法必须满足方法的签名必须与委托一致,并且返回类型也是要一致的。(方法签名:包括参数的个数、类型和顺序;返回类型不包含在放哪广发签名里)。

2、委托的使用

使用的方式当然是Show出代码来解释最清楚了。

class Program
{
  //1、使用delegate关键字来定义一个委托类型
  delegate void MyDelegate(int para1,int para2);
  static void Main(string[] args)
  {
    /2、声明委托变量d
    MyDelegate d;

    //3、实例化委托类型,传递的方法也可以为静态方法,这里传递的是实例方法
    d=new MyDelegate(new Program().Add);

    //4、委托类型作为参数传递给另一个方法
    MyMethod(d);
    Console.ReadKey();
  }

  //该方法的定义必须与委托定义相同,即返回类型为void,两个int类型的参数
  void Add(int para1,int para2)
  {
    int sum=para1+para2;
    Console.WriteLine("两个数的和为:"+sum);
  }

  //方法的参数是委托类型
  Private static void MyMethod(MyDelegate mydelegate)
  {
    //5、在方法中调用委托
    mydelegate(1,2);
  }
}

从上面的代码可以得出委托使用的步骤:定义委托类型->声明委托变量->实例化委托->作为参数传递给方法->调用委托。

3、为什么要引入委托?

委托最大的作用,就是使得一个方法可以作为另一个方法的参数进行传递。

比如我们要实现一个打招呼的方法,但每个国家打招呼的方式是不一样的,我们可能会使用switch的方式进行设计,但这样做明显导致可扩展性不足,每次增加一个新的打招呼方法都必须去修改case语句来适应新的需求。如果有了委托,情况就不一样了:

class Program
{
  //定义委托类型
  public delegate void GreetingDelegate(string name);
  static void Main(string[] args)
  {
    //引入委托之后
    Program p=new Program();
    p.Greeting("李志",p.ChineseGreeting);
    p.Greeting("Tommy Li",p.EnglishGreeting);
    Console.ReadKey();
  }

  public void Greeting(string name,GreetingDelegate callback)
  {
    callback(name);
  }

  public void ChineseGreeting(string name)
  {
    Console.WriteLine("你好,"+name);
  }

  public void EnglishGreeting(string name)
  {
    Console.WriteLine("Hello,"+name);
  }
}

在引入委托之后,就可以把函数作为参数传递给另一个方法了。委托可以提高方法的可扩展性。

4、委托的本质

委托是一个类类型,从哪里看得出来呢,就需要从IL代码中找到答案。

C#代码如下:

class Program
{
  public delegate void DelegateTest(int param);
  static void Main(string[] args)
  {
  }
}

从上图中便可以得出委托DelegateTest是一个类,继承自System.MulticastDelegate类型。并且该类包含了一个构造函数和3个方法。有了构造函数,我们才能使用new关键字来实例化委托类型。而Invoke方法则用来显式地调用委托。此外,BeginInvoke和EndInvoke是两个异步方法(以后解释什么叫做异步方法)。

在最开篇开始的代码当中,我们使用mydelegate(1,2)来调用方法,这是隐式调用,其背后也是要通过调用Invoke方法来调用委托的。当时,我们使用显式调用mydelegate.Invoke(1,2)也行。

5、委托链

C#中的委托同样可以封装多个方法。C#中把封装多个方法的委托称作委托链或多路广播委托。

可以通过“+=”运算符,将多个委托对象链接到一个委托对象实例上,成为多路广播委托实例。也可以使用“-=”运算符将某个委托从委托链对象上移除。

class Program
{
  //声明一个委托类型
  public delegate void DelegateTest();
  static void Main(string[] args)
  {
    //用静态方法来实例化委托
    DelegateTest dtstatic =new DelegateTest(Program.Method1);
    DelegateTest dtinstance=new DelegateTest(new Program().Method2);

    //定义一个委托对象,一开始初始化为null,即不代表任何方法
    DelegateTest delegatechain=null;

    //使用“+”符号链接委托,链接多个委托后就成为了委托链
    delegatechain+=dtstatic;
    delegatechain+=dtinstance;

    //delegatechain-=dtinstance;
    //调用委托链
    delegatechain();
    Console.Read();
  }

  private static vodid Method1()
  {
    Console.WriteLine("这是静态方法");
  }

  private void Method2()
  {
    Console.WriteLine("这是实例方法");
  }
}

总结:委托,是C#中一个最基本最重要的特性。大家可以借助反编译工具好好看一下委托的IL代码。

添加一下委托的内部构造,说明了为什么可以形成一个委托链。

C#世界中的委托的更多相关文章

  1. C# 中的委托和事件

    觉得这篇文章写的非常好,大神之作,由简入繁,对我这种初学者来说帮忙很大,特此留存下. 摘自:http://tracefact.net/CSharp-Programming/Delegates-and- ...

  2. Objective-C中的委托(代理)模式

    我个人更喜欢把委托(Delegate)模式称为代理(Proxy)模式.还是那句话,第一次接触代理模式是在Java中接触的,在Java中实现代理模式和接口是少不了的.当时学习Spring的时候用到了接口 ...

  3. C# 中的委托和事件(转)

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  4. C# 中的委托和事件(转载)

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  5. 【转】C# 中的委托和事件

    阅读目录 C# 中的委托和事件 引言 将方法作为方法的参数 将方法绑定到委托 事件的由来 事件和委托的编译代码 委托.事件与Observer设计模式 .Net Framework中的委托与事件 总结 ...

  6. 第3章 C#中的委托和事件

    .NET框架中的委托和事件 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  7. 分分钟用上C#中的委托和事件之窗体篇

    上次以鸿门宴的例子写了一篇名为<分分钟用上C#中的委托和事件>的博文,旨在帮助C#初学者迈过委托和事件这道坎,能够用最快的速度掌握如何使用它们.如果觉得意犹未尽,或者仍然不知如何在实际应用 ...

  8. 《C#高级编程》学习笔记------C#中的委托和事件(续)

    本文转载自张子阳 目录 为什么要使用事件而不是委托变量? 为什么委托定义的返回值通常都为void? 如何让事件只允许一个客户订阅?(事件访问器) 获得多个返回值与异常处理 委托中订阅者方法超时的处理 ...

  9. c#中的委托和事件(转)

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

随机推荐

  1. 冒烟测试、α测试、Beta测试、性能测试

    “冒烟测试”(也可称为showcase)这一术语描述的是在将代码更改嵌入到产品的源树中之前对这些更改进行验证的过程. 冒烟测试(smoke test)在测试中发现问题,找到了一个Bug,然后开发人员会 ...

  2. 理解I/O Completion Port

    欢迎阅读此篇IOCP教程.我将先给出IOCP的定义然后给出它的实现方法,最后剖析一个Echo程序来为您拨开IOCP的谜云,除去你心中对IOCP的烦恼.OK,但我不能保证你明白IOCP的一切,但我会尽我 ...

  3. vijosP1629 八

    vijosP1629 八 链接:https://vijos.org/p/1629 [思路] 暴力容斥(看他们都这么叫=_=)+精度选择. 总体思路是先统计LR区间内满足是8倍数的数目ans,再从ans ...

  4. 武汉Uber优步司机奖励政策(2月1日~2月7日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  5. Ubuntu下Django初体验(二)——创建工程及应用

    一.工程目录详解 创建工程后得到如下目录: 1. manage.py 管理项目.创建数据库.启动服务器等.测试等. 查看子命令: python manage.py 启动服务器: python mana ...

  6. jni编译non-numeric second argument to `wordlist' function错误

    在jni编译过程中,遇到non-numeric second argument to `wordlist' function错误,个人遇到这个错误的原因,是因为从windows中拷贝了Android. ...

  7. JSBinding+Bridge:逻辑代码中操作二进制数据

    以这2个函数为例 class File { public static byte[] ReadAllBytes(string path); public static void WriteAllByt ...

  8. engine中调整Element的上下显示顺序(遮盖)

    pGraphicsContainer.AddElement(pElement, 0); Engine中IGraphicsContainer类似于栈,加Element时,默认加到第一个,所以会将之前加的 ...

  9. word模版另存为网页(*.htm,*.html),转为jsp页面并加入数据后导出成word

    word模版另存为网页之后,将html格式的文件转为jsp页面,在页面上加入相应的动态值,加入的值中包含图片,这个该怎么处理??另外导出的文件需要拷贝到不同的地方(无法联网)使用. <%@ pa ...

  10. 利用图片延迟加载来优化页面性能(jQuery)

    图片延迟加载也称懒加载,常用于页面很长,图片很多的页面,以电子商务网站居多,比如大家常上的京东,淘宝,页面以图居多,整个页面少说几百K,多则上兆,如果想一次性加载完成,不仅用户要哭了,服务器也得哭了. ...