zoukankan      html  css  js  c++  java
  • C#世界中的委托

    委托是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代码。

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

  • 相关阅读:
    异或交换真的比开一个tmp快吗?
    淘宝前端团队的干货《论版本号的正确打开方式》
    箭头函数
    js对象引用问题
    json+underscore+Node 小例子
    fs.stat()
    Express static静态路由
    剑指offer(二) 替换空格
    Node实现简单的表单+图片上传+路由
    剑指offer(一) 二维数组的查找
  • 原文地址:https://www.cnblogs.com/Helius/p/5363169.html
Copyright © 2011-2022 走看看