委托和lambda表达式,Action和Func
1、为什么要用委托
我们为什么要有委托?任何东西存在即合理,不合理的也会被时间淘汰掉,委托既然存在肯定有存在的必要,我们来看一下什么时候可以用到委托。
接下来我们有个需求,就是调用一个方法,取出1-1000个数字中所有是10的倍数的数字
public static List<int> GetNum() {
List<int> lst = new List<int>();
//这个算法是最简陋的,但是举这个例子是最合适的
for (int i = ; i < ; i++)
{
if (i%==) {
lst.Add(i);
}
}
return lst;
}
这个很好写,但是如果有一天,我们的需求变了,想取出1-1000个数字中所有是8的倍数的数字,那我们应该怎么写?是不是只要将if里面的条件改为i%8==0就行了,但是有一点变动的话就修改方法,说明这个方法写的并不好,如果方法很复杂的话修改也很艰难。可能有人会说在添加一个获取是8的倍数的方法,这样的话会增加数据冗余,也就是重复的内容。
如果我们可以传递方法的话,只要传过来一个(有一个参数为int类型返回值为Boolean类型的方法),这个问题将不是问题
public static List<int> GetNum(有一个int类型的参数返回值为Boolean类型的方法) {
List<int> lst = new List<int>();
for (int i = ; i < ; i++)
{
if (有一个int类型的参数返回值为Boolean类型的方法) {
lst.Add(i);
}
}
return lst;
}
是不是我们将想要获取什么样的数字这个操作来交给了调用者,无论调用者想获取1-1000以内什么样的数字都可以完成。但是这个方法的前提就是可以传递方法,这个时候我们就需要用到委托了。
2、委托如何使用
委托其实就是一个能够指向方法的 指针,定义了一个委托就是定义了一个 类型
首先我们先来定义一个委托,也就是定义一个类型
//访问修饰符 委托关键字 方法的返回值类型 要定义的类型名(参数1,参数2.....);
public delegate Boolean DelegateFunc(int x);
委托定义好了,也就是说我们已经定义好了一个DelegateFunc类型,这个类型的使用方法就和public class DelegateFunc{}写了一个类是一样的,因为都是定义了一个类型,既然大家都是类型,那用法肯定都是一样的,我们先来看一下声明普通的类型是如何声明的
//类型 变量名 = 实例化一个Object类型的对象(构造函数有无参数)
Object obj = new Object();
而DelegateFunc既然也是我们定义好的一个类型,那用法自然一样(因为构造函数需要参数,所以下面这样写是不对的,没有传入参数)
//类型 变量名 = 实例化一个DelegateFunc类型的对象(构造函数有无参数)
DelegateFunc func = new DelegateFunc();
委托是一个能够指向方法的指针,而它的构造函数就是需要一个方法,接着我们来定义一个返回值为Boolean,能接收一个int类型参数的方法
//相当于方案1
public static Boolean Condition1(int i)
{
//模拟复杂的操作 相当于return i%10==0;
int x = i % ;
if (i % == )
{
return true;
}
else {
return false;
}
}
定义好了方法我们再来实例化一个DelegateFunc类型的对象
//构造函数放入方法的话不需要带(),带()的话是调用
DelegateFunc func = new DelegateFunc(Condition1);
下面看一下下面这种声明委托类型的方式
//同样都是类型Object类型可以这样写
//因为String最终是继承自Object,并且String可以默认转换为Object
Object obj = "obj";
//而DelegateFunc也可以通过这种方式赋值,这说明Condition1可以默认转换为委托类型
DelegateFunc func = Condition1;
实例化完成之后func变量就会指向Condition1方法,调用方式如下
//调用委托类型的对象和调用普通的方法是一样的
func();
然后我们把刚才写的GetNum方法修改为如下的样子,参数为接收一个DelegateFunc类型的参数,也就是委托类型
public static List<int> GetNum(DelegateFunc func)
{
List<int> lst = new List<int>();
for (int i = ; i < ; i++)
{
//调用传过来的方法,根据调用者传过来的方法拿到想要的数字
if (func(i))
{
lst.Add(i);
}
}
return lst;
}
在Main方法中调用GetNum方法
//声明委托
DelegateFunc func = new DelegateFunc(Condition1);
//调用方法
List<int> lst = GetNum(func);
//也可以直接调用,因为都会默认转换
//List<int> lst = GetNum(Condition1);
//输出
foreach (int item in lst)
{
Console.WriteLine(item);
}
输出

如果我们有新的方案的话,只需要在新建一个方案,然后传入方法中,比如我们还看刚才那个求1-1000以内8的倍数,我们只需要声明一个新的方案
//声明一个新的方案2
public static Boolean Condition2(int i) {
//同样模拟复杂的操作 相当于return i%8==0;
int x = i % ;
if (i % == )
{
return true;
}
else {
return false;
}
}
然后和刚才一样,声明一个委托就行,传入GetNum就行。
不过我们看一下,虽然已经比较简化代码了,但是写起来还是很麻烦,然后我们来看一下lambda表达式
3、lambda表达式
首先lambda表达式只是方法的一种写法!lambda声明的方法是匿名方法,它和委托并不是绑死的,这是两个东西,但是lambda表达式和委托结合使用是非常常见的!
看一下lambda表达式的语法,也就是函数的另一种写法
//可以这样写
//DelegateFunc func = new DelegateFunc((i) =>
//{
// return i % 8 == 0;
//});
//也可以这样 不进行new DelegateFunc操作,因为会默认转换
//如果有多句的话,这样写每一句通过分号隔开
DelegateFunc func = (i) => { return i % == ; };
//如果只有单句 不用写return 默认reuturn i%8==0 这一句计算出来的值
func = (i) => i % == ;
//如果只有一个参数 多个参数的话要(i,j,....)这样写
func = i => i % == ;
除此之外lambda也可以用来声明方法,貌似只能写一句,,,,
//无返回值
public static void HelloWord() => Console.WriteLine("Hello Word!");
//有返回值
public static String GetHelloWord() => "Hello Word!";
有了lambd我们再来调用GetNum,就会变得非常方便
//8的倍数
List<int> lst = GetNum((i) => i % == );
//10的倍数
lst = GetNum(i => i % == );
//20的倍数
lst = GetNum(i => i % == );
4、Action和Func
Action和Func是微软已经定义好的的两种委托类型,区别是Action是没有返回值的,而Func是需要返回值的
Action使用方法
//无参数
Action action1 = () => Console.WriteLine("action");
//有参数的话调用Action<T>
Action<int> action2 = (i) => Console.WriteLine(i);
//多个参数就在生命的时候<T,T,T>
Action<int,string> action3 = (i, str) => Console.WriteLine(i+"\t"+str);
//调用
action1();
action2();
action3(,"s");
运行结果:

Func使用方法
//Func是没有Func类型的,只有Func<T>类型
Func<string> func1 = () => "func";
//如果需要参数 Func<T,T,T>
//最后一个T类型为返回值类型,前面的全都为参数的类型!!!
Func<string, int> func2 = (i) => int.Parse(i);
//如果有多个参数 最后一个T类型为返回值类型,前面的全都为参数的类型!!!
Func<int, string, int> func3 = (i, str) => int.Parse(i + str); //调用
Console.WriteLine(func1());
Console.WriteLine(func2(""));
Console.WriteLine(func3(,""));
运行结果

委托和lambda表达式,Action和Func的更多相关文章
- 委托、Lambda表达式、事件系列06,使用Action实现观察者模式,体验委托和事件的区别
在"实现观察者模式(Observer Pattern)的2种方式"中,曾经通过接口的方式.委托与事件的方式实现过观察者模式.本篇体验使用Action实现此模式,并从中体验委托与事件 ...
- 委托、Lambda表达式、事件系列05,Action委托与闭包
来看使用Action委托的一个实例: static void Main(string[] args) { int i = 0; Action a = () => i++; a(); a(); C ...
- 委托、匿名委托、Lambda 表达式、Expression表达式树之刨根问底
本篇不是对标题所述之概念的入门文章,重点在阐述它们的异同点和应用场景.各位看官,这里就不啰嗦了,直接上代码. 首先定义一个泛型委托类型,如下: public delegate T Function&l ...
- 十二、C# 委托与Lambda表达式(匿名方法的另一种写法)
委托与Lambda表达式 1.委托概述 2.匿名方法 3.语句Lambda 4.表达式Lambda 5.表达式树 一.委托概述 相当于C++当中的方法指针,在C#中使用delegate 委托来 ...
- 系统预定义委托与Lambda表达式
NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式 开篇:在上一篇中,我们了解了匿名类.匿名方法与扩展方法等所谓的新语法,这一篇我们继续征程,看看系统预定义委托(Action/Fun ...
- C# Note2:委托(delegate) & Lambda表达式 & 事件(event)
前言 本文主要讲述委托和Lambda表达式的基础知识,以及如何通过Lambda表达式实现委托调用,并阐述.NET如何将委托用作实现事件的方式. 参考:C#高级编程 1.什么是委托(delegate)? ...
- 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理
委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...
- 委托学习过程及委托、Lambda表达式和匿名方法的关系总结及事件总结
第一章,当开始学习委托的时候,我们会问什么是委托?为什么要学习委托? 一,什么是委托? 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, ...
- C# 委托(delegate)、泛型委托和Lambda表达式
目录 # 什么是委托 # 委托声明.实例化和调用 1.声明 2.委托的实例化 3.委托实例的调用 4.委托完整的简单示例 #泛型委托 1.Func委托 2.Action委托 3.Predicate委托 ...
- C# 委托 (一)—— 委托、 泛型委托与Lambda表达式
C# 委托 (一)—— 委托. 泛型委托与Lambda表达式 2018年08月19日 20:46:47 wnvalentin 阅读数 2992 版权声明:此文乃博主之原创.鄙人才疏,望大侠斧正.此 ...
随机推荐
- Maven(一)Maven 的概念和安装
Maven 的概念和安装 Maven 是什么 首先 Maven 肯定是一个造福人类的好东西,它可以省去我们构建项目中引入 jar 包时的麻烦,还有利于项目的模块化开发等等等好处.在如今项目中大体都是使 ...
- TCP、UDP和HTTP简述整理
http:是用于www浏览的一个协议.tcp:是机器之间建立连接用的到的一个协议. 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层.在网络层有IP协议.ICMP协议.ARP协议.R ...
- 五分钟了解Zabbix
Zabbix-简介 Zabbix概念 Zabbix组成 Server Zabbix server 是 Zabbix agent 向其报告可用性.系统完整性信息和统计信息的核心组件.是存储所有配置信息. ...
- Ansible配置文件ansible.cfg详解
Ansible是一个系列文章,我会尽量以通俗易懂.诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些. Ansible系列博文直达链接:Ansible入门系列 前言 此时外面小雨淅淅沥沥 ...
- HDU - 1232 畅通工程【并查集】
畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 个人永久性免费-Excel催化剂功能第102波-批量上传本地图片至网络图床(外网可访问)
自我突破,在100+功能后,再做有质量的功能,非常不易,相对录制视频这些轻松活,还是按捺不住去写代码,此功能虽小,但功课也做了不少,希望对真正有需要的群体带来一些惊喜. 背景介绍 图床的使用,一般是写 ...
- 学习git使用网址
如何将本地项目上传到Github (随梦飞翔) https://www.cnblogs.com/smfx1314/p/8426115.html git学习 GUI https://blog.csdn. ...
- C#写进程守护程序
最近写了好多次进程守护程序,今天在这里总结一下. 用到的知识点: 1.在程序中启动进程, 2.写Windows服务, 3.以及在Windows服务中启动带界面的程序 关于第三点的问题,我在我的上一篇博 ...
- win8上安装sql server (2008 and 2008 R2)存在兼容性问题怎么解决
安装sql2008R2之前,需要先下载"AccessDatabaseEngine"组件并安装(百度上搜索下载就可以了),打补丁重启,再安装sql2008,安装时候提示兼容性问 ...
- sql server还原数据库(请选择用于还原的备份集)
还原数据库的时候明明选择了备份集,还是提示未选择还原的备份集 后来查了下,是因为我本地有两个数据库(2008R2和2014),对应的两个数据库实例.而还原bak是sqlserver2014的备份,我默 ...