全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

C#委托与匿名委托详解

本来是想写一篇《委托与lambda表达式的前世今生》,但仅委托部分已经写了很多内容,于是就此分开关于Lambda表达是的内容后续再写吧。

不知道Lambda表达式是谁发明的,只记得第一次接触Lambda表达式是在使用VS2008的时候,那就先认为是微软发明的吧。

Lambda表达式从我接触开始到现在变得越来越流行,Java8中开始支持、kotlin更是对C#,F#做了广泛的抄袭(C#曾几何时不也如此对待过Java嘛)。其实这都充分说明了,Lambda表达式的重要性。要搞清楚Lambda首先需要搞清楚委托。

委托:

假设现在我们要开发一个处理两个整数的程序(假设先处理相加操作)

public class Worker
    {
      /// <summary>
      /// 处理两个数
      /// </summary>
      /// <param name="a"></param>
      /// <param name="b"></param>
      /// <returns></returns>
      public int HandleTwoNumber(int a,int b)
      {
        return a + b;
      }
    }
static void Main(string[] args)
    {
      int a = int.Parse(Console.ReadLine());
      int b = int.Parse(Console.ReadLine());

      Worker worker = new Worker();
      int result = worker.HandleTwoNumber(a, b);
      Console.WriteLine(String.Format("Result:{0}", result));

      string p = Console.ReadLine();
}

如果一段时间后,我们需要它变更为减操作:

public class Worker
    {
      public int HandleTwoNumber(int a,int b)
      {
        return a - b;
      }
    }

虽然有a+b变为a-b的变化很微小,但后续此处可能面临多次变化(由减变为除.........)。有变化就应封装变化,此处我们可以将a与b的操作行为抽象出来,用什么抽象呢?委托

public class Worker
    {
      public delegate int TwoNumberHandleMethodDelegate(int x, int y);
      public int HandleTwoNumber(int a,int b)
      {
        return a + b;
      }
    }

public delegate int TwoNumberHandleMethodDelegate(int x, int y);此处用delegate标注,表明这是一个委托定义。如果去掉 delegate 再来观察该定义,你会发现这就是一个没有方法体的抽象方法。所以委托的含义即:与该抽象方法签名形式相同的方法的类型。委托就是一种你定义的新数据类型,它与int、class是一样的都是数据类型。int表示整数,只要是整数都可以赋值给 int型变量;TwoNumberHandleMethodDelegate则表示,接收两个int型参数并返回int型结果的这类方法,因此满足上述要求的方法都可赋值给TwoNumberHandleMethodDelegate类型的变量。

如此一来Worker代码可修改为:

public class Worker
    {
      public delegate int TwoNumberHandleMethodDelegate(int x, int y);
      public int HandleTwoNumber(int a, int b, TwoNumberHandleMethodDelegate handle)
      {
        return handle(a, b);
      }
    }

如此a、b的操作被封装起来,所有的变化均交由调用者来处理。此处的含义:HandleTwoNumber处理a、b两个整数,具体如何处理由 handle 实施。此时你可能会问,那如何来调用该方法呢?调用如下:

private static int Add(int a, int b)
    {
      return a + b;
    }

    private static int Sub(int a, int b)
    {
      return a - b;
    }

    static void Main(string[] args)
    {
      int a = int.Parse(Console.ReadLine());
      int b = int.Parse(Console.ReadLine());
      Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add);
      Worker worker = new Worker();
      int result = worker.HandleTwoNumber(10, 10,method);
       //int result = worker.HandleTwoNumber(10, 10, Sub);//简化版
      Console.WriteLine(String.Format("Result:{0}", result));
 }

根据上面的程序可知,Main代码块为worker的调用者,作为调用者而言应该最清楚自己想要让woker做的工作。因此作为被调用者的worker而言,它只需要接收调用者Main给的a\b参数及执行Main定制的算法method,然后按照算法执行并返回结果即可。上面代码虽然简单,但其中的意义深远,随着编程时间的增加相信你的理解将越深刻。

委托变量在进行赋值时除了标准的方式,还可以进行简化:

Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add);
      Worker worker = new Worker();
      int result = worker.HandleTwoNumber(10, 10,method);
//可简化为
// int result = worker.HandleTwoNumber(10, 10,Add);

编译器将自动检查Add是否符合 TwoNumberHandleMethodDelegate 的定义,如果符合允许直接将方法名赋值给委托变量。

匿名委托

通过上面的示例代码,我们很容易发现 TwoNumberHandleMethodDelegate method 变量被赋值为Add(Sub),因此在调用method(...)时相当于调用Add(.....)。这样一来就可以认为

method与Add完全等效,既然等效那是否可以直接将Add的定义内容赋值给method变量呢?答案是肯定的:

static void Main(string[] args)
    {

      Worker.TwoNumberHandleMethodDelegate method =private static int Add(int a, int b)
    {
      return a + b;
    };
}

但像上面这种生拉硬套是不行的,你还需要做修改。修改内容是:因为现在的代码处于Main方法中,访问修饰符去掉,同样static也应去掉;同时编译器知道你要给method赋值,那么要赋的这个值肯定满足返回类型为int的要求,所有int在此时就多余了去掉;因为赋值之后method就等效于Add,以后调用只要通过method变量就可完成,所有Add方法名不需要去掉。如此代码变为如下形式:

static void Main(string[] args)
    {

      Worker.TwoNumberHandleMethodDelegate method =  (int a, int b)
    {
      return a + b;
    };
}

经过上面的修改内容简化了很多,但method赋值的=右端是什么东西呢?此时编译器并不能正确识别这是一个方法,因为方法的定义需要满足包含:访问修身符、返回类型、方法名、参数列表、方法体五部分内容。虽然你心里清楚这是个简化了的方法,但是编译器不懂你的心.........,那没关系只要我们告诉编译器,后面的是个简化方法就可以了。

static void Main(string[] args)
    {

      Worker.TwoNumberHandleMethodDelegate method =  delegate(int a, int b)
    {
      return a + b;
    };
}

正如你所期望的那样,现在编译器已经知道了=右侧是你经过简化的方法;ok,现在可以正常赋值并使用了。

通过上面的定义我们发现,用delegate标注的简化方法没有一个像Add/Sub一样固定的名字。因此我们称这种方法叫匿名委托(我习惯称匿名方法)。

你可能还注意到该匿名委托定义完毕后就赋值给Main代码快中的局部变量method,因此当超出method的作用域后,该方法就再也没有机会调用了。这引出了匿名方法、匿名委托、匿名函数它们的最常见用法,即用来定义只需要使用一次的功能代码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# C#  # 委托  # 匿名委托  # 详解c# 委托链  # c# 委托的本质是什么  # C# 引入委托的目的是什么  # 一篇文章彻底搞清楚c#中的委托与事件  # C#用委托BeginInvoke做异步线程  # C#使用委托的形式调用线程代码实例  # C#沉淀之委托的深入讲解  # C# WPF 通过委托实现多窗口间的传值的方法  # C#匿名委托与Lambda表达式详解  # c# 委托详解  # c# 委托的常见用法  # 调用者  # 这是一个  # 就可以  # 都是  # 是一个  # 是个  # 是在  # 还可以  # 也没  # 在此  # 不需要  # 不懂  # 有机会  # 很容易  # 我们可以  # 这就  # 微软  # 用了  # 这类  # 要做 


相关文章: 如何在Golang中使用encoding/gob序列化对象_存储和传输数据  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  ui设计制作网站有哪些,手机UI设计网址吗?  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  如何快速搭建FTP站点实现文件共享?  中山网站制作网页,中山新生登记系统登记流程?  如何高效利用亚马逊云主机搭建企业网站?  高防服务器租用指南:配置选择与快速部署攻略  免费视频制作网站,更新又快又好的免费电影网站?  教学论文网站制作软件有哪些,写论文用什么软件 ?  建站之星如何快速解决建站难题?  nginx修改上传文件大小限制的方法  如何快速搭建高效香港服务器网站?  威客平台建站流程解析:高效搭建教程与设计优化方案  如何挑选优质建站一级代理提升网站排名?  制作营销网站公司,淘特是干什么用的?  如何在阿里云域名上完成建站全流程?  网站制作报价单模板图片,小松挖机官方网站报价?  linux top下的 minerd 木马清除方法  建站主机选购指南与交易推荐:核心配置解析  如何高效完成独享虚拟主机建站?  ,在苏州找工作,上哪个网站比较好?  如何快速搭建高效WAP手机网站吸引移动用户?  如何在企业微信快速生成手机电脑官网?  c# 在ASP.NET Core中管理和取消后台任务  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  如何选购建站域名与空间?自助平台全解析  深入理解Android中的xmlns:tools属性  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  php8.4新语法match怎么用_php8.4match表达式替代switch【方法】  宝塔建站后网页无法访问如何解决?  详解jQuery停止动画——stop()方法的使用  建站之星图片链接生成指南:自助建站与智能设计教程  javascript基本数据类型及类型检测常用方法小结  建站OpenVZ教程与优化策略:配置指南与性能提升  做企业网站制作流程,企业网站制作基本流程有哪些?  如何访问已购建站主机并解决登录问题?  广州商城建站系统开发成本与周期如何控制?  企业宣传片制作网站有哪些,传媒公司怎么找企业宣传片项目?  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  javascript中的try catch异常捕获机制用法分析  广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?  如何通过服务器快速搭建网站?完整步骤解析  重庆网站制作公司哪家好,重庆中考招生办官方网站?  如何在自有机房高效搭建专业网站?  c# 在高并发场景下,委托和接口调用的性能对比  黑客入侵网站服务器的常见手法有哪些?  如何用虚拟主机快速搭建网站?详细步骤解析  香港服务器租用费用高吗?如何避免常见误区? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。