Linq(一)
Linq是c#设计者们在c#3.0中新添加的语法:查询表达式。使用查询表达式,很多标准查询操作符都能转化成更容易理解的代码,也就是和SQL风格非常接近的代码。
在介绍Linq之前,先介绍下泛型集合IEnumerable<T>,IEnumerable泛型接口可以在指定数据源进行迭代操作,它定义了一些扩展方法,可以对数据源进行操作。在Linq中,数据源实际是实现了对接口IEnumerable<T>的类,通过selsect返回的结果页实际是一个类。
Exposes the enumerator, which supports a simple iteration over a collection of a specified type.
这是msdn上给出的解释,一切foreach都是基于IEnumerable。在实际应用中,查询表达式输出哦几乎总是IEnumerable<T>或者它的派生类型。
下面看一段代码,简单的查询表达式:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace LinqBasic {
class Program {
private static string[] keyWords = { "it", "has", "been", "a", "long", "day", "to", "see", "you", "myfriend" }; public static void ShowWordContains() {
IEnumerable<string> selection = from word in keyWords where word.Contains("t") select word;
//此处将IEnumerable<string>换成var依旧可以,程序会根据选择的结果自动推断出查询的类型。
ShowWordContains(selection);
} public static void ShowWordContains(IEnumerable<string> selection){
foreach (string keyword in selection) Console.WriteLine(keyword);
}
static void Main(string[] args) { ShowWordContains();
Console.ReadLine(); }
}
}
输出:it
to
在这个查询中,表达式总是以from子句开头,以select或者group by 结尾。from子句中的标识符word称为范围变量,代表集合中的每一项。这就很像是foreach循环变量代表集合中的没一项。
熟悉sql的开发者会发现,Linq和sql有非常相近的语法。最明显的区别是 c#查询的子句顺序首先是from子句,然后是where子句,最后才是select子句。而对应的sql查询首先是select,然后是from,最后是where。
#查询表达式的顺序其实更接近于各个操作在逻辑上的顺序,对查询进行求值时,首先指定集合from,再筛选出想要的项,(where),最后描述希望的结果(select)。
最后,c#查询表达式的顺序确保变量的作用域规则与局部变量的规则保持一致。例如,子句(通常是from)子句先声明变量,然后才能使用这个变量。
投射:
查询表达式的结果是IEnumerable<T>类型的集合。T的实际类型是从select或者group by子句推到出来的。例如 在上面的代码,编译器知到keywords是string[]类型,能穿花为IEnumerable<string>类型,所以推到出word是string类型,查询以select
word结尾,所以查询表达式是字符串集合,所以就算是匿名类型var,编译器也知道实际类型。
其实,输出类型还可以有别于输入类型,关键在于select子句的投射,如下面的代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace LinqBasic {
class Program {
static void List1(string rootDirectory, string searchExtension) {
IEnumerable<string> files = Directory.GetFiles(rootDirectory, searchExtension);
IEnumerable<FileInfo> fileInfos = from file in files select new FileInfo(file);
foreach (FileInfo fileinfo in fileInfos) {
Console.WriteLine("filename:{0}, \tfileLaseWriteTime:{1}", fileinfo.Name, fileinfo.LastAccessTime);
}
} static void Main() {
List1(@"G:\c#\depositaryManagingSystem",@"*.cs");
Console.ReadLine();
}
}
}
输出:
filename:depositary.cs, fileLaseWriteTime:2015/7/1 17:44:21
filename:depositary.Designer.cs, fileLaseWriteTime:2015/6/25 19:32:42
filename:Form1.cs, fileLaseWriteTime:2015/6/22 23:44:19
filename:Form1.Designer.cs, fileLaseWriteTime:2015/6/22 23:44:19
filename:Program.cs, fileLaseWriteTime:2015/6/17 10:17:38
filename:注册管理员.cs, fileLaseWriteTime:2015/6/22 23:55:15
filename:注册管理员.Designer.cs, fileLaseWriteTime:2015/6/25 19:34:32
这个查询表达式的结果是一个IEnumerable<fileinfo>,而不是Directoy.Getfiles()返回的Ienumerable<string>类型,查询表达式的select子句可以将from子句的表达式所收集到的东西完全投射到完全不同的数据类型中。
注意: 将上面的查询结果强数据类型转化成var匿名类型是完全可以的。
如下面的代码段:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace LinqBasic {
class Program {
static void List1(string rootDirectory, string searchExtension) {
var files = Directory.GetFiles(rootDirectory, searchExtension);
var fileresults = from file in files
select new {
Name = file,
LastWriteName = File.GetLastWriteTime(file)
};
foreach (var fileresult in fileresults) {
Console.WriteLine("filename:{0}, \tfileLaseWriteTime:{1}\n", fileresult.Name, fileresult.LastWriteName);
}
} static void Main() {
List1(@"G:\c#\depositaryManagingSystem",@"*.cs");
Console.ReadLine();
}
}
}
在这个例子中,我们只投射出了文件名和他最后一次的写入时间。
程序运行结果
可以看出,Directory.Getfiles()这个静态方法可以得到文件的全名。而FileInfos.Name这个属性只能得到文件名。
关于文件的知识,将在不久后讲解。
初学者主题:查询表达式的推迟执行
我们现在来考虑我的第一个代码段,对selection赋值的时候,创建查询和向变量赋值不会执行查询,而只是生成代表查询的对象。换言之,查询对象创建时不会调用word.contains()方法。查询表达式只是存储了一个条件(查询标准)。以后再遍历有selection变量所标识的集合时会用到这个条件。
下面我们在来看一段代码来检测这个发生。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace LinqBasic {
class Program {
private static string[] keyWords = { "it", "has", "been", "a", "long", "day", "to", "see", "you", "myfriend" };
public static void ShowKeywords() {
IEnumerable<string> selections = from word in keyWords where IsKeyWord(word) select word; Console.WriteLine("Query created");
foreach (string str in selections) Console.WriteLine(str);
}
private static bool IsKeyWord(string word) {
Console.WriteLine("~~~");
if (word.Contains("t")) return true;
return false;
}
static void Main() {
ShowKeywords();
Console.ReadLine();
}
}
}
程序输出:
可以看到,在query created 之前并没有任何输出,在foreach对集合的输出是,才调用方法IsKeyWord();
总之 虽然selection是集合(毕竟他的类型是IEnumerable<T>),但在赋值时,from子句之后的一切都构成了选择条件。遍历selection时才会真正应用这些条件。
现在来考虑第二个例子:
今天七夕要早睡,剩下的明天继续吧。
Linq(一)的更多相关文章
- Linq表达式、Lambda表达式你更喜欢哪个?
什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- [C#] 走进 LINQ 的世界
走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...
- [C#] 进阶 - LINQ 标准查询操作概述
LINQ 标准查询操作概述 序 “标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法.大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了IEnumerable<T> ...
- LINQ to SQL语句(7)之Exists/In/Any/All/Contains
适用场景:用于判断集合中元素,进一步缩小范围. Any 说明:用于判断集合中是否有元素满足某一条件:不延迟.(若条件为空,则集合只要不为空就返回True,否则为False).有2种形式,分别为简单形式 ...
- .NET深入实战系列—Linq to Sql进阶
最近在写代码的过程中用到了Linq查询,在查找资料的过程中发现网上的资料千奇百怪,于是自己整理了一些关于Linq中容易让人困惑的地方. 本文全部代码基于:UserInfo与Class两个表,其中Cla ...
- LINQ Group By操作
在上篇文章 .NET应用程序与数据库交互的若干问题 这篇文章中,讨论了一个计算热门商圈的问题,现在在这里扩展一下,假设我们需要从两张表中统计出热门商圈,这两张表内容如下: 上表是所有政区,商圈中的餐饮 ...
- Entity Framework 6 Recipes 2nd Edition(11-9)译 -> 在LINQ中使用规范函数
11-9. 在LINQ中使用规范函数 问题 想在一个LINQ查询中使用规范函数 解决方案 假设我们已经有一个影片租赁(MovieRental )实体,它保存某个影片什么时候租出及还回来,以及滞纳金等, ...
- Entity Framework 6 Recipes 2nd Edition(11-11)译 -> 在LINQ中调用数据库函数
11-11. 在LINQ中调用数据库函数 问题 相要在一个LINQ 查询中调用数据库函数. 解决方案 假设有一个任命(Appointment )实体模型,如Figure 11-11.所示, 我们想要查 ...
- Entity Framework 6 Recipes 2nd Edition(13-6)译 -> 自动编译的LINQ查询
问题 你想为多次用到的查询提高性能,而且你不想添加额外的编码或配置. 解决方案 假设你有如Figure 13-8 所示的模型 Figure 13-8. A model with an Associat ...
随机推荐
- day11---异步IO\数据库\队列\缓存
一.RabbitMQ队列 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息 ...
- 百度地图api(摘自百度)
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- Ubuntu 12.04 改造指南
文章转自:http://www.lupaworld.com/article-217719-1.html 升级12.04已经有一段时间了.作为一个从08年就开始用Ubuntu的老用户,我觉得作为一个LT ...
- ABP框架详解(五)Navigation
ABP框架中的Navigation功能用于管理业务系统中所有可用的菜单导航控件,通常在业务系统的首页会有一个全局性的导航菜单,JD商城,天猫,猪八戒网莫不如是.所以为方便起见,Navigation功能 ...
- crtmpserver系列(二):搭建简易流媒体直播系统
crtmpserver简介 我们在第一章的时候已经简要说明了crtmpserver,crtmpserver是一个由C++语言编写的开源的RTMP流媒体服务器,与其对应的商业产品自然是Adobe公司的F ...
- diff详解,读懂diff结果
1.概述 本文将要讨论的是diff命令,diff用来比较两个文件.当然文件比较的工具很多,windows系统下面就有不错的工具可以使用,例如常用的Beyond Compare,WinMerge都是图形 ...
- ENode 2.0 - 深入分析ENode的内部实现流程和关键地方的幂等设计
前言 ENode是一个基于消息的架构,使用ENode开发的系统,每个环节都是处理消息,处理完后产生新的消息.本篇文章我想详细分析一下ENode框架内部是如何实现整个消息处理流程的.为了更好的理解我后面 ...
- 人人都是 DBA(VI)SQL Server 事务日志
SQL Server 的数据库引擎通过事务服务(Transaction Services)提供事务的 ACID 属性支持.ACID 属性包括: 原子性(Atomicity) 一致性(Consisten ...
- [每日电路图] 7、设计一个PCB的流程及细节·总结——给外行的同学或刚入行的同学一个宏观鸟瞰电路板设计的大致流程的文章
前言 最近两天使用AD14软件设计了一个蓝牙防丢器电路板(PCB)图纸,中间有一些细节在本文中记录下,方便下次设计PCB时参考.也希望能给外行的同学或刚入行的同学一个宏观鸟瞰电路板设计的大致流程的文章 ...
- Springlake-02 权限&文档设置&Role设置&Folder设置&登录
1. 权限 有3个默认的权限用户: 1.System Owner so 管理员权限全部:Type Setup; Group Setup; Form Setup; Role Setup; Share R ...