重学c#系列——委托和匿名函数[二十五]
前言
简单介绍一下什么是委托。
正文
以前也写过委托,这次算是重新归档,和新的补充吧。
https://www.cnblogs.com/aoximin/p/13940125.html
有些人说委托是函数指针的包装,也有些人说委托是一个方法或多个方法的引用。
这都是没有问题,委托是一个概念,微软官方文档说委托是一种引用类型,表示对具有特定参数列表和返回类型的方法引用。
我觉得太啰嗦了,实际上就是方法的引用。
上面都是委托的概念,但是实现方式每种语言可能都不一样。
比如c++ 和 c 用的是函数指针,而c# 用的是生成包装类(等下IL),当然本质还是函数指针。
那么来看下委托。
internal class Program
{
delegate int TestDelegate(int a);
static void Main(string[] args)
{
TestDelegate a = test;
a(0);
}
public static int test(int a)
{
return 0;
}
}
将test 给了委托a,然后调用的时候直接a()就可以了。
用起来十分简单。
实际上对IL来说其实是没有委托这个概念的,通过反编译来看下原理。
private static void Main(string[] args)
{
TestDelegate a = new TestDelegate(test);
a(0);
}
实际上会生成TestDelegate这样一个类,然后将test 引用添加进去。
来看下il。
再看下TestDelegate是一个什么样的类。
就是把调用的object 和 方法的引用放入包装类中了,然后invoke 可以进行调用。
如果是多个方法的引用呢?
internal class Program
{
delegate int TestDelegate(int a);
static void Main(string[] args)
{
TestDelegate a = test;
a += test;
a(0);
}
public static int test(int a)
{
return 0;
}
}
看下IL:
原理就是又new了一个TestDelegate,然后用Delegate 将两个相连。
Combine 是一个静态方法哈。
本质是调用a的combineImp这个方法。之所以有这个一个静态方法是为了避免出现a为空的情况,如果a为空,直接把b给a啊。
这个是我们写链式结构可以学习的,这样就不用判断声明的时候是否为空。
然后c# 帮我们提取定义了很多委托,以至于我们几乎不用去声明委托。
比如Func 和 Action,Func 有返回值,Action没有。
下面介绍匿名函数,匿名函数有两个要介绍的,他们分别是匿名方法和lambda表达式。
他们原理都一样,都是生成匿名函数,只是写法不一样。
delegate int TestDelegate(int a);
static void Main(string[] args)
{
TestDelegate a = delegate (int a)
{
return 0;
};
}
看下反编译后的内容。
private static void Main(string[] args)
{
TestDelegate a = <>c.<>9__1_0 ?? (<>c.<>9__1_0 = new TestDelegate(<>c.<>9.<Main>b__1_0));
}
那么看下<>c 这个类:
首先看到第一个框,那么作者的意思是想把 <>c做成一个单例。
里面有委托的引用。然后下面这个
b__1_0 就是生成的方法。
其实匿名方法还是编译帮忙生成对应的方法名。
如果用lambda 表达式写的话,那么是这样写的:
这种写法编译出来的代码一模一样。只是不同写法的问题。
值得注意的是匿名函数如果引用了外部的信息,那么会形成闭包。
比如说:
static void Main(string[] args)
{
Student s = new Student();
TestDelegate a = (a) => {
s = null;
return 0;
};
a += (b) => {
return 0;
};
a += (c) => {
return 0;
};
}
首先b和c(第二个和第三个匿名)没有引用外部对象,那么都会生成在<>c这个类中。
第一个有外部引用生成了另外一个类。
然后实例化<>c__DisplayClass1_0后,那么会将s赋值进来。
所以会形成这种闭包,这是值得注意的地方。
结
下一节委托的发布订阅与事件。
重学c#系列——委托和匿名函数[二十五]的更多相关文章
- Hadoop MapReduce编程 API入门系列之Crime数据分析(二十五)(未完)
不多说,直接上代码. 一共12列,我们只需提取有用的列:第二列(犯罪类型).第四列(一周的哪一天).第五列(具体时间)和第七列(犯罪场所). 思路分析 基于项目的需求,我们通过以下几步完成: 1.首先 ...
- 3 委托、匿名函数、lambda表达式
委托.匿名函数.lambda表达式 在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法.C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方 ...
- 用委托、匿名函数、Lambda的方式输出符合要求的数
最近看了一些博客,对委托和匿名函数和Lambda的方式有了一些更深的理解,在前人的基础上.我也写3个例子 using System; using System.Collections.Generic; ...
- C#匿名委托,匿名函数,lambda表达式
一.类型.变量.实例之间的关系. 类型>变量>实例 类型可以创建变量,实体类可以创建实例,实例可以存储在变量里. 二.委托使用过程: 1.定义委托(写好签名): 2.创建委托变量: 3.给 ...
- CSharp委托与匿名函数
CSharp委托与匿名函数 场景 面对事件处理,我们通常会通过定义某一个通用接口,在该接口中定义方法,然后在框架代码中,调用实现该接口的类实例的方法来实现函数的回调.可能这样来说有些抽象,那我们提供一 ...
- 重学c#系列——字典(十一)
前言 重学c#系列继续更新,简单看一下字典的源码. 看源码主要是解释一下江湖中的两个传言: 字典foreach 顺序是字典添加的顺序 字典删除元素后,字典顺序将会改变 正文 那么就从实例化开始看起,这 ...
- 面向对象的基本特征:封装(接口 、struct、枚举、委托、匿名函数) 继承,多态。
如何理解面向对象的基本特征:封装 我们通过接口 .struct.枚举.委托.泛型.匿名函数的去理解封装 接口 .struct.枚举.委托.泛型.匿名函数有什么区别?我们通过这些IL探究真相,案例如下: ...
- C#基础系列——委托和设计模式(二)
前言:前篇 C#基础系列——委托实现简单设计模式 简单介绍了下委托的定义及简单用法.这篇打算从设计模式的角度去解析下委托的使用.我们知道使用委托可以实现对象行为(方法)的动态绑定,从而提高设计的灵活性 ...
- 《手把手教你》系列技巧篇(二十五)-java+ selenium自动化测试-FluentWait(详细教程)
1.简介 其实今天介绍也讲解的也是一种等待的方法,有些童鞋或者小伙伴们会问宏哥,这也是一种等待方法,为什么不在上一篇文章中竹筒倒豆子一股脑的全部说完,反而又在这里单独写了一篇.那是因为这个比较重要,所 ...
- 委托,匿名函数和lambda表达式
很早之前就接触到了委托,但是一直对他用的不是太多,主要是本人是菜鸟,能写的比较高级的代码确实不多,但是最近在看MSDN微软的类库的时候,发现了微软的类库好多都用到了委托,于是决定好好的研究研究,加深一 ...
随机推荐
- 03-MyBatisPlus的CRUD 接口
一.insert 1.插入操作 @RunWith(SpringRunner.class) @SpringBootTest public class CRUDTests { @Autowired pri ...
- vue3+three.js实现疫情可视化
前言 自成都九月份以来疫情原因被封了一两周,居家着实无聊,每天都是盯着微信公众号发布的疫情数据看,那种页面,就我一个前端仔来说,看着是真的丑啊!(⊙_⊙)?既然丑,那就自己动手开整!项目是2022.9 ...
- 如何在Windows中批量创建VMware的虚拟机
在最近的工作中,需要创建一批类似的机器.在VMware中创建了模板,然后根据自义向导部署之后,发现可以快速的完成新vm的部署.系统中的计算机名,IP地址都可以自动的完成更新.唯一的缺点是,系统自带的向 ...
- Kubernetes 存储卷详解
转载自:https://mp.weixin.qq.com/s/Ywx3ju6FP0IShOgI757XYA Volumes 默认情况下容器中的磁盘文件是非持久化的,对于运行在容器中的应用来说面临两个问 ...
- Pod原理
Pod 是 Kubernetes 集群中最基本的调度单元,我们平时在集群中部署的应用都是以 Pod 为单位的,而并不是我们熟知的容器,这样设计的目的是什么呢?为何不直接使用容器呢? 为什么需要 Pod ...
- HashMap底层原理及jdk1.8源码解读
一.前言 写在前面:小编码字收集资料花了一天的时间整理出来,对你有帮助一键三连走一波哈,谢谢啦!! HashMap在我们日常开发中可谓经常遇到,HashMap 源码和底层原理在现在面试中是必问的.所以 ...
- 为什么 CRM 能帮助装备制造企业进行数字化转型?
CRM确实能帮助装备制造企业进行数字化转型,体现在销售管理端,能方便的服务于"客户需求"为主旨的数字化转型思想,用客户的需求来指导生产等.但这个说法有点片面,毕竟那只是客户管理部分 ...
- 洛谷P2863 [USACO06JAN]The Cow Prom S (tarjan)
题目简述:一个有向图,求出这个图点数>1的强连通分量的个数. 那么就是tarjan求强联通分量的模板了. 记得要用一个数组标记节点是否在栈中. 1 #include<bits/stdc++ ...
- 洛谷P4638 SHOI2011 银行 ( 最大流)
类似题目(一模一样):http://poj.org/problem?id=1149 我这里以poj1149的PIGS为例, 新建源点s和汇点t,n个顾客作为中间的点,,对于每个顾客,他可以解锁一定的猪 ...
- Java Style的C++容器流式处理类
很久没有上博客园了,最近一段时间,因为工作的关系时间上比较闲,利用闲暇时间重新翻了一下丢弃很久的C++语言.C++从98.11.14.17目前已经也走到了20版本,发生了很多变化,也引入了很多新的语言 ...