C#中委托、匿名函数、Lambda表达式的一些个人理解
0x01定义一个委托,相当于定义一个可以存储方法的特殊变量类型
下面我们看具体的代码,通过代码更好理解
delegate void IntMethodInvoker(int x);
这行代码就是声明一个委托,其中delegate是关键字,表示声明一个委托,void是要存储的方法的返回类型,IntMethodInvoker是声明的委托类型名字,结合最开始的那句话就是自定义的类书变量类型名,int x则是要存储的方法的返回类型
这样一个委托可以存放哪些方法呢?
只要返回类型一致,参数列表一致的方法都能存储
在这个例子中,就是返回类型为void,有一个int形参的方法
void test(int t)
{
Console.WriteLine("Just a test" + t )
}
如这样的test方法就可以存储到IntMethodInvoker委托的实例中
委托是一种特殊类型的对象,定义好委托之后就可以创建它的实例了然后存储方法
IntMethodInvoker DelegateTest = test;
这行代码即将test方法的地址存放到IntMethodInvoker委托的实例DelegateTest中,在以后只需要调用DelegateTest就能执行test方法。
DelegateTest(32);
这行代码与test(32)效果相同
委托可以添加多个方法引用,添加多个方法引用的委托叫多播委托
添加多个方法引用使用+=,若要删除添加的方法引用使用-=
0x02使用委托可以将方法当作参数传递
既然前面说了委托类似于定义一个可以存储方法的特殊变量类型,那么我们也可以将这个特殊类型作为方法的形参,将一个方法引用添加到委托实例中,然后将委托实例作为另一个接受委托类型参数的方法的实参,就达到了将方法传递给另一个方法的效果
class Program
{
static void Main(string[] args)
{
Test test = new Test();
Test.TestDelegate testDelegate = new Test.TestDelegate(test.Fun);
test.KK(testDelegate);
}
}
class Test
{
public delegate void TestDelegate();
public void Fun()
{
Console.WriteLine("这是一个简单的方法!");
}
public void KK(TestDelegate testDelegate)
{
Console.WriteLine("这是一个接收委托的方法");
testDelegate();
}
}
这是一个将委托作为参数,将一个方法传递给另一个方法的例子
在这个例子中,先声明了一个Test实例,然后声明了一个TestDelegate委托实例testDelegate
testDelegate委托包含了test.Fun()的引用,这时并没有调用test.Fun(),只是保存了引用
接下来执行test.KK(testDelegate),这时testDelegate委托作为形参传递到了KK方法中
KK方法在调用testDelegate();时,委托执行Fun方法
所以最后的执行结果是
这是一个接收委托的方法
这是一个简单的方法!
0x03Func<T>和Action<T>
委托非常常用,所以.Net内置了两个委托类型,这样我们就不用自己去声明委托了
Action<T>泛型委托,表示引用一个void返回类型的方法。这个委托存在不同的变体,可以接受需要0 ~ 16个参数的方法
Func<T>泛型委托,与Action<T>相似,但是表示引用一个有一个返回值类型的方法。Func<T>同样可以接收0 ~ 16个参数的方法,默认最后一个是返回类型,即Fun<T>最多有十七位参数
Func<string,string,int>
这个Func表示可以接收一个参数列表为两个string,返回一个int的方法。
0x03Lambda和匿名方法
匿名方法:
Func<string, string> anonDel = delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
匿名方法的作用:
委托是存储方法的引用,也就是说,要用委托,就必须要先有方法,但是实际上有很多时候委托所存储的方法引用只会在委托或者事件(事件基于委托)中使用,这时候我们单独定义一个方法很麻烦,这时候就可以使用匿名方法,上方就是一个匿名方法,我们看右边
delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
这个就是匿名方法,使用delegate关键字,如果我们把delegate换成一个普通的名字
KK (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
这就是一个普通的方法(结尾的分号是Fun委托赋值语句的结尾),所以匿名方法就是一个普通的方法将方法名去掉换成delegate,以达到简化代码的目的
Func<string, string> anonDel =
delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
这样看是不是很好理解了
Lambda表达式:
在我的理解中,Lambda表达式其实是为了简化匿名方法
我们依然用上面的代码
//匿名方法
delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
}
//Lambda表达式
(string pram) =>
{
param += mid;
param += " and this was added to the string.";
return param;
}
这两个是等价版本, =>就是Lambda运算符,现在我们看它的两边是什么,左边是参数列表,右边是方法体。
这个Lambda其实有一点复杂了,通常我们遇到的Lambda会更简化
- 如果只有一个参数,只需要参数名就足够了,即这个Lambda中,可以将(string pram)改写为pram
- 如果方法体只有一行语句,那么在方法块中就不需要花括号和return语句
举个例子
Func<double,double> square = (double x) =>
{
return x*x;
};
这个Lambda表达式可以简写为
Func<double,double> square = x => x*x
Lambda表达式的闭包问题
这里就一句话,在Lambda表达式使用了外部的变量(不是Lambda表达式内的变量),外部的变量的值在调用时决定,而不是定义Lambda表达式时决定
int someVal = 5;
Func<int, int> ZZ = x => x + someVal;
someVal = 7;
Console.WriteLine(ZZ(3));
最后输出的时7,因为ZZ委托调用Lambda表达式时someVal已经等于7了
C#中委托、匿名函数、Lambda表达式的一些个人理解的更多相关文章
- (28)C#委托,匿名函数,lambda表达式,事件
一.委托 委托是一种用于封装命名和匿名方法的引用类型. 把方法当参数,传给另一个方法(这么说好理解,但实际上方法不能当参数,传入的是委托类型),委托是一种引用类型,委托里包含很多方法的引用 创建的方法 ...
- Qt中使用匿名函数lambda表达式
一.为什么要使用匿名函数lamdba 首先,lambda表达式可以使代码变得简单,C++中,一个lambda表达式表示一个可调用的代码单元.如代码: #include <QCoreApplica ...
- 【Unity|C#】基础篇(9)——匿名函数 / Lambda表达式
[学习资料] <C#图解教程>(第13章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...
- Python中的匿名函数lambda的用法
一.lambda函数的简介 对lambda函数,它其实是一个类似于def的函数,只不过lambda是一个不需要定义函数名的匿名函数.当我们在有些时候,需要做一些简单的数学计算时,如果定义一个def函 ...
- 委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件【转】
1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委 ...
- 匿名函数 lambda表达式(lambda expression)
阅读g2log时,发现有两行代码居然看不懂. 1. auto bg_call = [this, log_directory]() {return pimpl_->backgroundChang ...
- C#多线程+委托+匿名方法+Lambda表达式
线程 下面是百度写的: 定义英文:Thread每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.进程也可能是整个程序或者是部分程序的动态执行.线程是一组指令的集合,或者是程序的特殊段,它 ...
- Python匿名函数——lambda表达式
如果要定义的函数很简单,一个return语句就能搞定,可以使用lambda表达式来定义, lambda表达式的语法如下: lambda parameters: expression lambda表达式 ...
- 【C#】委托中的匿名函数与lambda
将方法作为方法的参数 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使 ...
- python做中学(八)匿名函数lambda的用法
匿名函数,顾名思义即没有名称的函数,和def定义的函数的最大区别在于匿名函数创建后返回函数本身(即匿名函数不需要return来返回值),表达式本身结果就是返回值,而def创建后则赋值给一个变量名,在P ...
随机推荐
- CodeForces - 915E 动态开点线段树
题目 晚上有n个亮着的灯泡,标号从1到n. 现在存在2种操作,如下: 操作1,关掉标号 [l,r] 区间的灯 操作2,打开标号 [l,r] 区间的灯 下面有q次询问,每次询问执行其中一种操作,询问格式 ...
- cin 与 getline
cin空格截断 getline(cin,s) 换行结束 ....太愚蠢了
- c# App.xaml
随着wpf自动创建的,是项目的起始点..Net先再App里找,找到了window然后开启window,项目真正的起始点是在App里. 这两个 (App 的xaml和cs文件)和MainWindow 的 ...
- HDU 4335 What is N?(指数循环节)题解
题意: 询问有多少数\(n\)满足\(n^{n!}\equiv b\mod p \land\ n\in[1,M]\),数据范围:\(M\leq2^{64}-1,p\leq1e5\) 思路: 这题显然要 ...
- 银河麒麟V10安装ASP.NET Core并配置Supervisor让网站开机自动运行
银河麒麟高级服务器操作系统V10是针对企业级关键业务,适应虚拟化.云计算.大数据.工业互联网时代对主机系统可靠性.安全性.性能.扩展性和实时性的需求,依据CMMI 5级标准研制的提供内生安全.云原生支 ...
- 翻译:《实用的Python编程》01_05_Lists
目录 | 上一节 (1.4 字符串) | 下一节 (1.6 文件) 1.5 列表 本节介绍 Python 原始数据类型列表(list). 列表是一种有序的集合. 创建列表 使用方括号 [] 来定义列表 ...
- 一个汉字在php中占几个字节?
问:一个汉字在php中占几个字节? 答: 对于中文字符,若使用 GBK.Big-5 版本,每个中文字符相当于 2 个字节: 若使用 UTF-8 版本,每个中文字符相当于 3 个字节.
- 图解 git stash
图解 git stash # 暂存本地 变化 $ git stash # 复原 $ git stash pop The "git stash" command can help y ...
- Next.js Conf 2020
Next.js Conf 2020 Next.js Conf Ticket https://nextjs.org/conf Conf Schedule https://confs.tech/javas ...
- LeetCode 刷题 App / LeetCode 题解 App
LeetCode 刷题 APP / LeetCode 题解 App 全端支持 http://leetcode-app.xgqfrms.xyz/ http://leetcode-desktop.xgqf ...