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 ...
随机推荐
- ubuntu12.04网络配置
1.配置/etc/network/interfaces #静态IP地址 auto lo iface lo inet loopback #loopback虚拟网络设备,使TCP/IP能以127.0.0. ...
- (转)Windows下的Memcached安装与使用
WHAT Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memc ...
- toolControls添加工具项
最近参考Arcengine的Samples做的功能,虽然简单,但是示例代码的确体现出了很好的封装性,值得学习,效果图如下: 闲话休絮,直入正题: 一.首先建立工具类,实现IMenuDef接口 clas ...
- 【原创】.NET之我见
最近在准备面试,自己也顺带巩固了下基础,加上自己对码农的一些理解都写在这里了,水平不行,欢迎吐槽 //.NET基础 1.Class 和struct 区别 类是一种“引用类型”.创建类的对象时,对象赋值 ...
- mac下android环境搭建笔记(android studio)
本文记录了本人在mac上配置android开发环境的一些过程,为了方便直接选用了官方的IDE– Android Studio .本文包括了android studio的安装.创建第一个hello wo ...
- UWP开发随笔——UWP新控件!AutoSuggestBox!
摘要 要开发一款优秀的application,控件肯定是必不可少的,uwp就为开发者提供了各种各样的系统控件,AutoSuggestBox就是uwp极具特色的控件之一,也是相对于之前win8.1的ua ...
- 图解集合5:不正确地使用HashMap引发死循环及元素丢失
问题引出 前一篇文章讲解了HashMap的实现原理,讲到了HashMap不是线程安全的.那么HashMap在多线程环境下又会有什么问题呢? 几个月前,公司项目的一个模块在线上运行的时候出现了死循环,死 ...
- 源代码版本管理与项目管理软件的认识与github的注册
源代码版本管理软件: 主要有:svn,cvs,hg,git,VSS 这些工具主要是一种记录代码更改历史, 可以无限回溯, 用于代码管理,多个程序员开发协作的工具.Perforce,StarTeam)- ...
- mac下apache配置,解决It is not safe to rely on the system's timezone settings.
之前一直转windows平台下做php,很少遇到问题.现在有了macbook,还在慢慢的熟悉中,搭建php开发环境,熟悉mac系统文档组织还有命令,颇费功夫. 今天我在mac下做一个php的练习,用到 ...
- Java-条件语句、循环语句练习
题目一:一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米)? double height=0.08; for(int i=1;i>0;i++) { heig ...