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(一)的更多相关文章

  1. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. [C#] 走进 LINQ 的世界

    走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...

  4. [C#] 进阶 - LINQ 标准查询操作概述

    LINQ 标准查询操作概述 序 “标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法.大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了IEnumerable<T> ...

  5. LINQ to SQL语句(7)之Exists/In/Any/All/Contains

    适用场景:用于判断集合中元素,进一步缩小范围. Any 说明:用于判断集合中是否有元素满足某一条件:不延迟.(若条件为空,则集合只要不为空就返回True,否则为False).有2种形式,分别为简单形式 ...

  6. .NET深入实战系列—Linq to Sql进阶

    最近在写代码的过程中用到了Linq查询,在查找资料的过程中发现网上的资料千奇百怪,于是自己整理了一些关于Linq中容易让人困惑的地方. 本文全部代码基于:UserInfo与Class两个表,其中Cla ...

  7. LINQ Group By操作

    在上篇文章 .NET应用程序与数据库交互的若干问题 这篇文章中,讨论了一个计算热门商圈的问题,现在在这里扩展一下,假设我们需要从两张表中统计出热门商圈,这两张表内容如下: 上表是所有政区,商圈中的餐饮 ...

  8. Entity Framework 6 Recipes 2nd Edition(11-9)译 -> 在LINQ中使用规范函数

    11-9. 在LINQ中使用规范函数 问题 想在一个LINQ查询中使用规范函数 解决方案 假设我们已经有一个影片租赁(MovieRental )实体,它保存某个影片什么时候租出及还回来,以及滞纳金等, ...

  9. Entity Framework 6 Recipes 2nd Edition(11-11)译 -> 在LINQ中调用数据库函数

    11-11. 在LINQ中调用数据库函数 问题 相要在一个LINQ 查询中调用数据库函数. 解决方案 假设有一个任命(Appointment )实体模型,如Figure 11-11.所示, 我们想要查 ...

  10. Entity Framework 6 Recipes 2nd Edition(13-6)译 -> 自动编译的LINQ查询

    问题 你想为多次用到的查询提高性能,而且你不想添加额外的编码或配置. 解决方案 假设你有如Figure 13-8 所示的模型 Figure 13-8. A model with an Associat ...

随机推荐

  1. 归并排序-java

    排序-归并排序 基本思想:是指将两个或两个以上的有序表合并成一个新的有序表. 具体步骤: (1首先将整个表看成是n个有序子表,每个子表的长度为1. (2)然后两两归并,得到n/2个长度为2的有序子表. ...

  2. alfresco install in linux, and integrated with tesseract ocr

    本文描述在Linux系统上安装Alfresco的步骤: 1. 下载安装文件:alfresco-community-5.0.d-installer-linux-x64.bin 2. 增加执行权限并执行: ...

  3. C#常用代码集合(1)

    引用自james li的博客,地址:http://www.cnblogs.com/JamesLi2015/p/3147986.html   1 读取操作系统和CLR的版本   OperatingSys ...

  4. MVC_Controller

    准备工作 安装VS2010或更高版本 安装数据库2008或更高版本 视个人系统不同配置IIS本地服务 数据库和VS下载地址 http://msdn.itellyou.cn/ 本节目标 通过本节案例对M ...

  5. 字符串反混淆实战 Dotfuscator 4.9 字符串加密技术应对策略

    因为手头需要使用一个第三方类库,网络上又找不到它的可用的版本,于是只好自己动手.这个类库使用了Dotfuscator 加密,用.NET Reflector加载程序集, 看到的字符串是乱码,如下面的代码 ...

  6. [.NET领域驱动设计实战系列]专题十:DDD扩展内容:全面剖析CQRS模式实现

    一.引言 前面介绍的所有专题都是基于经典的领域驱动实现的,然而,领域驱动除了经典的实现外,还可以基于CQRS模式来进行实现.本专题将全面剖析如何基于CQRS模式(Command Query Respo ...

  7. UWP滑动后退

    经过近些年智能手机App的不断发展,用户已经不仅仅满足于功能上的需求.UI.设计等非功能点逐渐在App体验中占了大多数的分数.不知从何时起,滑动手势就成为了App的一个标配.他不仅仅是一个功能,更是一 ...

  8. Javascript aop(面向切面编程)之around(环绕)

    Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被 ...

  9. 团队项目——站立会议DAY6

    团队项目--站立会议 DAY6        团队成员介绍(5人):张靖颜.何玥.钟灵毓秀.赵莹.王梓萱        今日(2016/5/13),站立会议已进行了一周时间,大家将这一周所遇到的问题和 ...

  10. 基于uploadify.js实现多文件上传和上传进度条的显示

    uploadify是JQuery的一个插件,主要实现文件的异步上传功能,可以自定义文件大小限制.文件类型.是否自动上传等属性,可以显示上传的进度条.官网地址是http://www.uploadify. ...