C#编程语法积累(二)
9、Lambda表达式
[1]Lambda表达式缩写推演,如下图:
[2]Lambda语句:=>右边有一个语句块(大括号"{}");Lambda表达式:=>右边只有一个表达式。
[3]Lambda本身无类型,不可赋值给var变量;
[4]编译时会生成一个静态方法,然后再实例化成委托传递使用;
Lambda详见:Lambda表达式
10、标准查询运算符(SQO)
"标准查询运算符"是组成语言集成查询 (LINQ) 模式的方法。大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了 "IEnumerable<T>"接口或 "IQueryable<T>" 接口。 标准查询运算符提供了包括筛选、投影、聚合、排序等功能在内的查询功能。
共有两组 LINQ 标准查询运算符,一组在类型为 "IEnumerable<T>"的对象上运行,另一组在类型为 "IQueryable<T>"的对象上运行。构成每组运算符的方法分别是 "Enumerable" 和 "Queryable" 类的静态成员。这些方法被定义为作为方法运行目标的类型的"扩展方法"。这意味着可以使用静态方法语法或实例方法语法来调用它们。
此外,许多标准查询运算符方法运行所针对的类型不是基于 IEnumerable<T>或 IQueryable<T>的类型。Enumerable类型定义两个此类方法,这些方法都在类型为 IEnumerable的对象上运行。利用这些方法(Cast<TResult>(IEnumerable)和 OfType<TResult>(IEnumerable)),您将能够在 LINQ 模式中查询非参数化或非泛型集合。 这些方法通过创建一个强类型的对象集合来实现这一点。Queryable类定义两个类似的方法(Cast<TResult>(IQueryable)和 OfType<TResult>(IQueryable)),这些方法在类型为 Queryable的对象上运行。
各个标准查询运算符在执行时间上有所不同,具体情况取决于它们是返回单一值还是值序列。返回单一值的方法(例如 Average 和 Sum)会立即执行。 返回序列的方法会延迟查询执行,并返回一个可枚举的对象。
对于在内存中集合上运行的方法(即扩展 IEnumerable<T>的那些方法),返回的可枚举对象将捕获传递到方法的参数。在枚举该对象时,将使用查询运算符的逻辑,并返回查询结果。
与之相反,扩展 IQueryable<T>的方法不会实现任何查询行为,但会生成一个表示要执行的查询的表达式树。查询处理由源 IQueryable<T>对象处理。
标准查询语法关键字:
[1]from 子句: 查询表达式必须以 from 子句开头。
(1)指定将对其运行查询或子查询的数据源;
(2)指定一个本地范围变量,表示源序列中的每个元素。范围变量和数据源都是强类型。from子句中引用的数据源的类型必须为 IEnumerable、IEnumerable<T>或一种派生类型(如 IQueryable<T>)。
例子10-1:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; // Create the query.
// lowNums is an IEnumerable<int>
var lowNums = from num in numbers
where num < 5
select num;
如例子10-1中,numbers为"数据源",num为"范围变量"。
[2]where 子句:
(1)where 子句用在查询表达式中,用于指定将在查询表达式中返回数据源中的"条件",并返回满足指定条件的元素。
(2)一个查询表达式可以包含多个 where 子句,一个子句可以包含多个"谓词"子表达式,在单一 where 子句内,可以使用 "&&" 和 "||" 运算符根据需要指定任意多个谓词。
在例子10-1中,where 子句筛选出除小于五的数字外的所有数字。如果移除 where 子句,则会返回数据源中的所有数字。表达式 num < 5 是应用于每个元素的谓词。
[3]select 子句:
(1)在查询表达式中,select 子句可以指定将在执行查询时产生的值的类型。
(2)该子句的结果将基于前面所有子句的计算结果以及 select 子句本身中的所有表达式。
(3)查询表达式必须以 select 子句或 group子句结束。
[4]group...by...子句:
(1)返回一个 IGrouping<TKey, TElement>对象序列,这些对象包含零个或更多个与该组的键值匹配的项 。
var stu0 =
from student in students
group student by student.Last[0];
(2)如果您想要对每个组执行附加查询操作,则可以使用 "into"上下文关键字指定一个临时标识符。使用 into 时,必须继续编写该查询,并最终用一个 select 语句或另一个 group 子句结束该查询,如下所示:
var stu1 =
from student in students
group student by student.Last[0] into g
orderby g.Key
select g;
(3)可通过orderby...thenby...指定次要排序
[5]into:可以使用 into 上下文关键字创建一个临时标识符,以便将 group、join 或 select 子句的结果存储到新的标识符中。此标识符本身可以是附加查询命令的生成器。在 group 或 select 子句中使用新标识符的用法有时称为"延续"。
string[] words = { "apples", "blueberries", "oranges", "bananas", "apricots"};
var wordGroups =
from w in words
group w by w[0] into fruitGroup
where fruitGroup.Count() >= 2
select new { FirstLetter = fruitGroup.Key, Words = fruitGroup.Count() };
[6]orderby 子句:
(1)可使返回的序列或子序列(组)按升序或降序排序。
(2)可以指定多个键,以便执行一个或多个次要排序操作。排序是由针对元素类型的默认比较器执行的。默认排序顺序为升序。还可以指定自定义比较器。 但是,只能通过基于方法的语法使用它。
string[] fruits = { "cherry", "apple", "blueberry" };
IEnumerable<string> sortAscendingQuery =
from fruit in fruits
orderby fruit //"ascending" is default
select fruit;
[7]...join...on...equals...子句:
(1)使用 join 子句可以将来自不同源序列并且在对象模型中没有直接关系的元素相关联。
(2)唯一的要求是每个源中的元素需要共享某个可以进行比较以判断是否相等的值。
(3)join句使用特殊的 "equals" 关键字比较指定的键是否相等。
(4) join子句执行的所有联接都是同等联接。
(5)join子句的输出形式取决于所执行的联接的具体类型。
(6)联接类型:内部联接; 分组联接; 左外连接;
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { ProductName = prod.Name, Category = category.Name }; //
含有 into 表达式的 join 子句称为分组联接。
var innerGroupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new { CategoryName = category.Name, Products = prodGroup };
在左外部联接中,将返回左侧源序列中的所有元素,即使它们在右侧序列中没有匹配的元素也是如此。若要在 LINQ 中执行左外部联接,请将 DefaultIfEmpty 方法与分组联接结合起来,以指定要在某个左侧元素不具有匹配元素时产生的默认右侧元素。可以使用 null 作为任何引用类型的默认值,也可以指定用户定义的默认类型。
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product { Name = String.Empty, CategoryID = 0 })
select new { CatName = category.Name, ProdName = item.Name };
[8]let 子句:
使用 "let" 关键字,可以存储子表达式的结果可以在随后的子句中使用,该关键字可以创建一个新的范围变量,并且用提供的表达式的结果初始化该变量。一旦用值初始化了该范围变量,它就不能用于存储其他值。但如果该范围变量存储的是可查询的类型,则可以对其进行查询。
string[] strings =
{
"A penny saved is a penny earned.",
"The early bird catches the worm.",
"The pen is mightier than the sword."
};
var earlyBirdQuery =
from sentence in strings
let words = sentence.Split(' ')
from word in words
let w = word.ToLower()
where w[0] == 'a' || w[0] == 'e'
|| w[0] == 'i' || w[0] == 'o'
|| w[0] == 'u'
select word;
[9]ascending 和 descending
(1)ascending :升序是默认排序顺序,所以您无须指定它。
(2)descending :降序
IEnumerable<string> sortDescendingQuery =
from vegetable in vegetables
orderby vegetable descending
select vegetable;
[10]in:
该上下文关键字可在下面三种上下文中使用:
(1)foreach 语句: foreach (var v in earlyBirdQuery) { Console.WriteLine("\"{0}\" starts with a vowel", v); }
(2)查询表达式中的 join 子句: from category in categories join prod in products on category.ID equals prod.CategoryID
(3)泛型接口和委托中的泛型类型参数。
11、LINQ查询表达式
本质:从Reflector中可以看到Linq最后都别转换成了标准查询语句。
[1]linq类似于Sql语句,以"from"子句开始,以"select"或"group...by..."子句结束;
[2]输出是一个IEnumerable<T>或 IQueryable<T>集合;"T的类型"是由select或group子句推断出来的。
class LINQQueryExpressions
{
static void Main()
{ // Specify the data source.
int[] scores = new int[] { 97, 92, 81, 60 }; // Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score; // Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}
C#编程语法积累(二)的更多相关文章
- Java基础之编程语法(二)
1.常量: 整型:整数,4个字节. 长整型:整数,8个字节.以L结尾. 单精度浮点数:小数,4个字节.以F结尾. 双精度浮点数:小数,8个字节. 布尔:只有两个值,真(true)或假(false),1 ...
- 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...
- C#多线程编程系列(二)- 线程基础
目录 C#多线程编程系列(二)- 线程基础 1.1 简介 1.2 创建线程 1.3 暂停线程 1.4 线程等待 1.5 终止线程 1.6 检测线程状态 1.7 线程优先级 1.8 前台线程和后台线程 ...
- C#编程总结(二)多线程基础
C#编程总结(二)多线程基础 无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作.要使应用程序能够快速响应 ...
- C#编程利器之二:结构与枚举(Structure and enumeration)【转】
C#编程利器之二:结构与枚举(Structure and enumeration) 在上一篇文章中,介绍了类如何封装程序中的对象.而实际中,出了类可以封装对象外,结构和枚举也可以封装一些对象,本文将着 ...
- Swift3.0基础语法学习<二>
对象和类: // // ViewController2.swift // SwiftBasicDemo // // Created by 思 彭 on 16/11/15. // Copyright © ...
- VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)
VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)-软件开发-鸡啄米 http://www.jizhuomi.com/software/141.html 上一讲中讲了VS20 ...
- python学习_数据处理编程实例(二)
在上一节python学习_数据处理编程实例(二)的基础上数据发生了变化,文件中除了学生的成绩外,新增了学生姓名和出生年月的信息,因此将要成变成:分别根据姓名输出每个学生的无重复的前三个最好成绩和出生年 ...
- .NET 4 并行(多核)编程系列之二 从Task开始
原文:.NET 4 并行(多核)编程系列之二 从Task开始 .NET 4 并行(多核)编程系列之二 从Task开始 前言:我们一步步的从简单的开始讲述,还是沿用我一直的方式:慢慢演化,步步为营. ...
随机推荐
- ueditor 百度编辑器,自定义右键菜单
如图:有2种自定义方法,一种是改源码,一种是初始化 初始化,如下代码: var ue = UE.getEditor('XXXid',{ // contextMenu:[ {label:'', cmdN ...
- OpenCV入门(2)- Java第一个程序
1.下载和安装OpenVC环境 从官方连接 https://opencv.org/releases.html 下载Windows的安装包 下载下来的就是一个压缩包,安装解压后,对Java开发有效的目录 ...
- 虚方法virtual、抽象方法abstract、接口interface区别
接口.抽象类.抽象方法.虚方法: 这四个名词时非常容易混淆的: 首先说一下接口 与抽象类 的异同: 相同点: 1.他们都不能实例化自己,也就是说都是用来被继承的. 2.抽象类中的抽象方法和接口方法一样 ...
- Androidstudio中jar包重复或jar包里的类重复问题
https://www.jianshu.com/p/dd5d4fda1df8 http://blog.csdn.net/hqb112233/article/details/51514208
- SpringAOP+注解实现简单的日志管理
今天在再次深入学习SpringAOP之后想着基于注解的AOP实现日志功能,在面试过程中我们也经常会被问到:假如项目已经上线,如何增加一套日志功能?我们会说使用AOP,AOP也符合开闭原则:对代码的修改 ...
- Ajax文件上传并添加Bootstrap进度条
1.项目中需要用到文件上传和显示进度,网上各种插件搞得头晕,决定自己实现一个 三个步骤:Ajax上传文件,获取上传进度,显示进度 html: <!DOCTYPE HTML> <htm ...
- MAC上mongodb连接不上
1.在Mac客户端里输入 mongo,发现mongo连接不上了,原因是mongo的服务没有开启. 2.在命令行了输入 mongod,开启服务的命令 3.启动起来以后,用mongo连接服务器.
- 【转】Python之xml文档及配置文件处理(ElementTree模块、ConfigParser模块)
[转]Python之xml文档及配置文件处理(ElementTree模块.ConfigParser模块) 本节内容 前言 XML处理模块 ConfigParser/configparser模块 总结 ...
- Python之matplotlib库学习
matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图.而且也可以方便地将它作为绘图控件,嵌入GUI应用程序中. 它的文档相当完备, ...
- 内核IS_ERR宏解析 【转】
转自:http://blog.chinaunix.net/uid-20196318-id-28769.html 最近在使用filp_open打开文件时遇到到一个问题,当打开一个并不存在的文件时,fil ...