C# 基础知识系列- 6 Lambda表达式和Linq简单介绍
前言
C#的lambda和Linq可以说是一大亮点,C#的Lambda无处不在,Linq在数据查询上也有着举足轻重的地位。
那么什么是Linq呢,Linq是 Language Intergrated Query
(语言集成查询)的缩写,可以对本地对象集合或者远程数据源进行结构化的查询操作。
那什么又是Lambda呢?嗯,简单来讲就是匿名函数,我们不声明方法名,只写一个方法体,这个方法体就是lambda表达式
lambda表达式
如何写一个lambda表达式
首先,在写lambda表达式之前,需要先了解 两个特殊的类型:Func
和Action
。
这是两个委托,这里先不急着了解什么是委托,可以把它们当做一种名称规范就行,它们都可以表示一个方法。不同的是其中Func
表示一个有返回值的方法,Action
表示一个没有返回值的方法。C#对这两个的定义如下:
public delegate TResult Func<out TResult>();//注意这里的out 表示这个泛型是返回值的类型泛型
public delegate void Action();
其中Func
和Action
各有16个变种:
// 注意 in 关键字,表示泛型是参数的类型约束
public delegate TResult Func<in T,out TResult>(T arg);
public delegate TResult Func<in T1,in T2,out TResult>(T1 arg1, T2 arg2);
……
public delegate TResult Func<in T1,in T2,in T3,in T4,in T5,in T6,in T7,in T8,in T9,in T10,in T11,in T12,in T13,in T14,in T15,in T16,out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
//
//
public delegate void Action<in T>(T obj);
public delegate void Action<in T1,in T2>(T1 arg1, T2 arg2);
……
public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7,in T8,in T9,in T10,in T11,in T12,in T13,in T14,in T15,in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
依次表示一个参数、两个参数、……十六个参数 的方法。当然,你还可以写更多的参数,但是如果一个方法的参数超过10个,为什么不用类封装起来呢?即使不封装,一个方法十几个参数,你确定不会被你的领导嫌弃吗。
言归正传,介绍完了Func
和Action
的定义,那么如果使用呢?
public void Demo1()
{
// 一个没有返回值,也没有参数的方法
}
Action act1 = Demo;// 直接给一个方法名
public void Demo2(string name)
{
//有一个参数,但没有返回值的方法
}
Action<string> act2 = Demo2;
public String Demo3()
{
// 有返回值,但没有参数的方法
}
Func<string> func1 = Demo3;
public int Demo4(double data)
{
// 返回值是int,有一个参数是double的方法
}
Func<double,int> func2 = Demo4;
以上是通过方法名获取Func
和Action
的方法,下面介绍一下通过Lambda表达式的方式创建Func
和Action
:
Action act1 = ()=> // lambda 的标志性 声明方式 =>
{
// 这是一个没有返回值,也没有参数的 lambda表达式
};
Action<int> act2 = (age) =>
{
// 这是一个 参数为int ,没有返回值的 lambda表达式
};
//=========================================
Func<string> func1 = () => ""; // 这是一个返回了空字符串的lambda表达式,注意这种写法
Func<string> func2 = () =>
{
return ""; //与上一个等价
}
Func<int,string> func3 = (age) =>
{
return "我的年纪是:"+age;// 一个参数是int,返回类型是string的lambda表达式
}
在lambda表达式中,当使用的是有返回值的方法体时,如果方法体是个简单的计算式或者说可以在一行内写完(或被编译器认为是一行)的话,可以省略 {
、}
和return
,直接用 =>
标记。
比如说以下内容:
Func<int,int,int> cal_area = (width, height) => width * height;// 计算面积
使用Lambda 表达式
现在我们手里有一大堆的Action
和Func
,我们该怎么用呢?
有以下两种常见的用法:
把它当做方法来用:
// 上接上文代码
act1();// 执行 act1 代表的方法或lambda表达式
act2(10); //执行act2 的lambda表达式
string str1 = func1();
string str2 = func3(10);
int area = cal_area(29,39);
调用Invoke方法:
act1.Invoke();
act2.Invoke(10);
area = cal_area.Invoke(33,63);
看过反射篇的应该对Invoke有一定印象,这个与MethodInfo里的Invoke类似,但是比其更加简单。
Linq 是什么
正如前言所述,Linq是一种对集合、数据源的集成式查询方式,它是对IEnumerable<T>
的扩展方法集,所以想要使用Linq的话,需要引用两个命名空间 System.Linq
和System.Linq.Expressions
。
Linq有两种使用方式,一种是通过方法链的方式调用,一种是类似SQL语句的方式进行数据查询。方法链是基础,类SQL方式是语法糖。下面简单介绍一下两种方式的使用,不过首先先假设我们有一个数据很多的集合:
IEnumerable<int> scores = new List<int>();//假设存放了某班50个人的语文成绩
使用方法链查询
获取分数大于60的所有分数:
IEnumerable<int> result1 = scores.Where(t => t > 60);
获取分数大于等于60的数量:
int count = scores.Count(t => t >= 60);
统计分数总和
int sum = scores.Sum();
获取所有分数个位上的数字:
IEnumerable<int> result2 = scores.Select(t => t % 10);
使用类SQL形式查询
查询所有大于等于60的分数:
IEnumerable<int> result3 = from score in scores
where score >= 60
select score;
简单介绍一下,类SQL形式有一个统一的格式写法,关键字from
、in
、select
缺一不可:
from 临时变量名 in 数据源
select 结果类型
where 是条件过滤,如果查询全部,可以忽略。
这种方式之所以被我称为是类SQL形式,是因为它的写法和SQL及其相似,熟悉SQL的可以很快上手。
为什么说方法链是基础呢?
因为SQL形式的查询里每一个关键字背后都有一个方法作为支撑,除了from 和in。
select 对应的Select 方法,where对应的Where方法。
需要特别注意的一点:
Linq查询是一种延迟查询,也就是说当返回类型是一个IEnumerable 的时候不会立即返回结果,必须调用ToList
才能获取到实际查询结果。另外需要注意的是,ToList
返回的是一个不可变List集合,这一点在集合篇中做过介绍了。
未完待续
C#里的Linq内容如此丰富,以至于一时间无法详细说明,后续还会有两到三篇关于Linq的内容,今天就先到这里了,感谢您的阅读。
更多内容烦请关注我的博客
C# 基础知识系列- 6 Lambda表达式和Linq简单介绍的更多相关文章
- 《Java基础知识》Java Lambda表达式
接触Lambda表达式的时候,第一感觉就是,这个是啥?我居然看不懂,于是开始寻找资料,必须弄懂它. 先来看一个案例: @FunctionalInterface public interface MyL ...
- [C# 基础知识系列]专题十六:Linq介绍
转自http://www.cnblogs.com/zhili/archive/2012/12/24/Linq.html 本专题概要: Linq是什么 使用Linq的好处在哪里 Linq的实际操作例子— ...
- C# 基础知识系列- 12 任务和多线程
0. 前言 照例一份前言,在介绍任务和多线程之前,先介绍一下异步和同步的概念.我们之间介绍的知识点都是在同步执行,所谓的同步就是一行代码一行代码的执行,就像是我们日常乘坐地铁通过安检通道一样,想象我们 ...
- C# 基础知识系列- 9 字符串的更多用法(一)
0. 前言 在前面的文章里简单介绍了一下字符串的相关内容,并没有涉及到更多的相关内容,这一篇将尝试讲解一下在实际开发工作中会遇到的字符串的很多操作. 1. 创建一个字符串 这部分介绍一下如何创建一个字 ...
- 基础知识系列☞C#中→属性和字段的区别
"好吧...准备写个'基础知识系列',算是记录下吧,时时看看,更加加深记忆···" 其实本来准备叫"面试系列"... 字段.属性.你先知道的哪个概念? ***我 ...
- 基础知识系列☞Abstract和Virtual→及相关知识
转载地址→http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的 ...
- 学习javascript基础知识系列第二节 - this用法
通过一段代码学习javascript基础知识系列 第二节 - this用法 this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascr ...
- 学习javascript基础知识系列第三节 - ()()用法
总目录:通过一段代码学习javascript基础知识系列 注意: 为了便于执行和演示,建议使用chrome浏览器,按F12,然后按Esc(或手动选择)打开console,在console进行执行和演示 ...
- [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)
引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...
随机推荐
- Spring MVC知识梳理
同上一篇博客,复习梳理SpringMVC知识点,这次的梳理比较快,很多细节没有顾虑到,后期可能会回来补充 1. 整体架构 1.1 在学习了SSM框架后我们来理清三者的应用层面 浏览器发送请求,请求到达 ...
- SDWebImage -- 封装 (网络状态检测,是否打开手机网络下下载高清图设置)
对SDWebImage 进行封装,为了更好的节省用户手机流量,并保证在移动网络下也展示高清图,对使用SDWebImage 下载图片之前进行逻辑处理,根据本地缓存中是否有缓存原始的图片,用户是否打开移动 ...
- 利用机器学习检测HTTP恶意外连流量
本文通过使用机器学习算法来检测HTTP的恶意外连流量,算法通过学习恶意样本间的相似性将各个恶意家族的恶意流量聚类为不同的模板.并可以通过模板发现未知的恶意流量.实验显示算法有较好的检测率和泛化能力. ...
- Jira字段配置最佳实践
在我们创建Jira时,Jira上会填写各式各样的字段,不同的字段对于不同的角色人员,使用方式也是不同的,通过这篇文章,希望大家能够对Jira使用有更深刻的认识. 为什么需要严格规范? 易于开发,测试, ...
- 关于HTTP那些事
写这篇文章的原因 记录前端性能优化用到的关键概念 简化大家对HTTP的学习 大家或许面试的时候可以用得到哦 HTTP是什么 Web的应用层协议(超文本传输协议HyperText Transfer Pr ...
- echart 新手踩坑
仪表盘踩坑 我采用的是单文件引入的方式来加载echarts图标也可以使用配置等方式详情参考文档,如果同学们要做出更加丰富的样式请参考文档配置手册配置手册:http://echarts.baidu.co ...
- AJAX 的 Ajax返回数据之前的loading等待效果(gif效果等)
首先,我们通过ajax请求,向后台传递参数,然后后台经过一系列的运算之后向前台返还数据,我希望在等待数据成功返还之前可以展示一个loading.gif图 不废话,在页面上执行点击事件(<a sc ...
- shell编程中星号(asterisk "*")的坑
今天分享一个有关shell编程中由通配符引起的问题. 1. 问题代码 cat test.logs 4567890 * ##*************************************## ...
- angular -——组件样式修改不成功
angular组件样式修改不成功! 自己定义的css可以成功 组件的不行 style在模板字符串里 直接没有 class 是显示的 但是样式不生效 加上面 即可,为什么?我也不太清楚.有知道答案的请回 ...
- Java基础 - Date的相关使用(获取系统当前时间)
前言: 在日常Java开发中,常常会使用到Date的相关操作,如:获取当前系统时间.获取当前时间戳.时间戳按指定格式转换成时间等.以前用到的时候,大部分是去网上找,但事后又很快忘记.现为方便自己今后查 ...