《C#本质论》读书笔记(15)使用查询表达式的LINQ

15.1 查询表达式的概念

15.1.1 投射
15.1.2 筛选
15.1.3 排序
15.1.4 let子句
15.1.5 分组
15.1.6 使用into进行查询延续
15.1.7 用多个from子句“平整”序列的序列

15.2 查询表达式作为方法调用

简单的查询表达式

  1. private static void ShowContextualKeywords1()
  2. {
  3. IEnumerable<string> selection = from word in Keywords
  4. where !word.Contains(‘*‘)
  5. select word;
  6. foreach (string keyword in selection)
  7. {
  8. Console.Write(" " + keyword);
  9. }
  10. }
  11. private static string[] Keywords = {
  12. "abstract", "add*", "alias*", "as", "ascending*", "base",
  13. "bool", "break", "by*", "byte", "case", "catch", "char",
  14. "checked", "class", "const", "continue", "decimal",
  15. "default", "delegate", "descending*", "do", "double",
  16. "dynamic*", "else", "enum", "event", "equals*",
  17. "explicit", "extern", "false", "finally", "fixed",
  18. "from*", "float", "for", "foreach", "get*", "global*",
  19. "group*", "goto", "if", "implicit", "in", "int",
  20. "into*", "interface", "internal", "is", "lock", "long",
  21. "join*", "let*", "namespace", "new", "null", "object",
  22. "on*", "operator", "orderby*", "out", "override",
  23. "params", "partial*", "private", "protected", "public",
  24. "readonly", "ref", "remove*", "return", "sbyte", "sealed",
  25. "select*", "set*", "short", "sizeof", "stackalloc",
  26. "static", "string", "struct", "switch", "this", "throw",
  27. "true", "try", "typeof", "uint", "ulong", "unchecked",
  28. "unsafe", "ushort", "using", "value*", "var*", "virtual",
  29. "void", "volatile", "where*", "while", "yield*"
  30. };

15.1.1 投射

查询表达式输出是一个IEnumerbale<T>或IQueryable<T>集合。T数据类型是从select或者groupby子句推导。

上例string数据类型是从 select word 推导的,因为word是一个字符串。word数据类型是由from子句所指定的IEnumerbale<T>集合的类型参数(这里是Keywords)。由于Keywords是一个string数组,它实现了IEnumerbale<T>,所以word是一个字符串。

表达式查询特定类型集合时,结果允许将数据投射成一个完全不同的类型。

Directory.GetCurrentDirectory()

  1. public static void Main()
  2. {
  3. List1(Directory.GetCurrentDirectory(),"*");
  4. }
  5. static void List1(string rootDirectory, string searchPattern)
  6. {
  7. IEnumerable<FileInfo> files =
  8. from fileName in Directory.GetFiles(
  9. rootDirectory, searchPattern)
  10. select new FileInfo(fileName);
  11. foreach (FileInfo file in files)
  12. {
  13. Console.WriteLine(".{0} ({1})",
  14. file.Name, file.LastWriteTime);
  15. }
  16. }

这里返回的是一个IEnumerable<FileInfo>,而不是System.IO.Directory.GetFiles()返回的IEnumerables<string>数据类型。

C#3.0引入匿名类型,很大程度上就是利用像这样的“投射”功能。

  1. var files =
  2. from fileName in Directory.GetFiles(
  3. rootDirectory, searchPattern)
  4. select new FileInfo(fileName);

15.1.2 筛选

where子句在垂直方向筛选集合。

  1. IEnumerable<string> selection = from word in Keywords
  2. where !word.Contains(‘*‘)
  3. select word;

15.1.3 排序

在查询表达式中对数据进行排序的是 orderby 子句。

  1. IEnumerable<string> fileNames =
  2. from fileName in Directory.GetFiles(
  3. rootDirectory, searchPattern)
  4. orderby (new FileInfo(fileName)).Length descending,
  5. fileName
  6. select fileName;

ascending和descending是上下文关键字,分别是升序或降序排序。

15.1.4 let子句

下面代码与上面的代码相似。问题是FileInfo要创建两次,分别在orderby 和 select子句中创建。

  1. public static void Main()
  2. {
  3. ListByFileSize2(Directory.GetCurrentDirectory(), "*");
  4. }
  5. static void ListByFileSize2(
  6. string rootDirectory, string searchPattern)
  7. {
  8. IEnumerable<FileInfo> files =
  9. from fileName in Directory.GetFiles(
  10. rootDirectory, searchPattern)
  11. orderby new FileInfo(fileName).Length, fileName
  12. select new FileInfo(fileName);
  13. foreach (FileInfo file in files)
  14. {
  15. //  As simplification, current directory is
  16. //  assumed to be a subdirectory of
  17. //  rootDirectory
  18. string relativePath = file.FullName.Substring(
  19. Environment.CurrentDirectory.Length);
  20. Console.WriteLine(".{0}({1})",
  21. relativePath, file.Length);
  22. }
  23. }

可以用let子句避免这种昂贵的开销。

  1. IEnumerable<FileInfo> files =
  2. from fileName in Directory.GetFiles(
  3. rootDirectory, searchPattern)
  4. let file = new FileInfo(fileName)
  5. orderby file.Length, fileName
  6. select file;
let 解释
  1. let子句引入了一个新的范围变量
  2. 它容纳的表达式值可以在查询表达式剩余部分使用
  3. 可以添加任意数量的let表达式,只需要它们每一个作为一个附加的子句
  4. 放在第一个from子句之后,最后一个select/group by子句之前,加入查询即可

15.1.5 分组

SQL中涉及对数据项进行聚合以生成一个汇总或合计或其他聚合值。

LINQ中表达力更强,LINQ允许将单独的项分组到一系列子集合中,还允许那些组与所查的集合中项关联

  1. private static void GroupKeywords1()
  2. {
  3. IEnumerable<IGrouping<bool, string>> selection =
  4. from word in keyWords
  5. group word by word.Contains(‘*‘);
  6. foreach (IGrouping<bool, string> wordGroup
  7. in selection)
  8. {
  9. Console.WriteLine(Environment.NewLine + "{0}:",
  10. wordGroup.Key ?
  11. "Contextual Keywords" : "Keywords");
  12. foreach (string keyword in wordGroup)
  13. {
  14. Console.Write(" " +
  15. (wordGroup.Key ?
  16. keyword.Replace("*", null) : keyword));
  17. }
  18. }
  19. }

结果 :


 查询结果是一系列IGrouping<bool,?string>类型元素。

查询生成一系列分组,将相同的bool类型键应用于组内的每个string。

在group子句后面选择一个匿名类型

  1. private static void GroupKeywords1()
  2. {
  3. IEnumerable<IGrouping<bool, string>> keywordGroups =
  4. from word in keyWords
  5. group word by word.Contains(‘*‘);
  6. var selection = from groups in keywordGroups
  7. select new
  8. {
  9. IsContextualKeyword = groups.Key,
  10. Items = groups
  11. };
  12. foreach (var wordGroup in selection)
  13. {
  14. Console.WriteLine(Environment.NewLine + "{0}:",
  15. wordGroup.IsContextualKeyword ?
  16. "Contextual Keywords" : "Keywords");
  17. foreach (var keyword in wordGroup.Items)
  18. {
  19. Console.Write(" " +
  20. keyword.Replace("*", null));
  21. }
  22. }
  23. }



 IGrouping<TKey,TElement>.Key 重命名为IsContextualKeyword,并命名了子集合属性Items。有人人为可以在匿名类型中添加一个属性来标识数据项的个数,然后,这个功能由wordGroup.Items.Count()提供。

15.1.6 使用into进行查询延续

来自为知笔记(Wiz)

时间: 2024-10-04 16:56:16

《C#本质论》读书笔记(15)使用查询表达式的LINQ的相关文章

《C++ Primer 4th》读书笔记 第5章-表达式

原创文章,转载请注明出处: http://www.cnblogs.com/DayByDay/p/3912114.html <C++ Primer 4th>读书笔记 第5章-表达式

C#复习笔记(4)--C#3:革新写代码的方式(查询表达式和LINQ to object(下))

查询表达式和LINQ to object(下) 接下来我们要研究的大部分都会涉及到透明标识符 let子句和透明标识符 let子句不过是引入了一个新的范围变量.他的值是基于其他范围变量的.let 标识符=表达式; 首先展示一个不适用let操作符来使用的按用户名称长度来排序: ... var queryWithoutLet = from user in SampleData.AllUsers orderby user.Name.Length select user; foreach (User us

十五、C# 使用查询表达式的LINQ

使用查询表达式的LINQ 本章介绍了一种新的语法,查询表达式. 1.查询表达式概述 2.特点:投射  筛选  排序   Let  分组 3.作为方法调用 标准查询运算符所实现的查询在功能上与SQL中实现的查询非常相似 C#3.0中添加了一个新的语法:查询表达式. 本章将介绍新的查询表达式语法,并利用这个语法对上一章的许多查询进行表示. 一.查询表达式概述 除了遍历集合中的所有项之外,开发者经常要执行的另一个操作是对集合进行筛选,目的是 最终只需要遍历数量较少的项,或者对集合进行投射,使其中的项变

《高性能MySQL》读书笔记--查询缓存

1.MySQL查询缓存 很多数据库产品都能够缓存查询的执行计划,对于相同类型的SQL就可以跳过SQL解析和执行计划生成阶段.MySQL还有另一种不同的缓存类型:缓存完整的SELECT查询结果,也就是"查询缓存". 查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生变化,那么和这个表相关的所有的缓存数据都将失效. 查询缓存对应用程序是完全透明的.应用程序无须关心MySQL是通过查询缓存返回的结果还是实际执行返回的结果. 另外,随着现在的通用服务器越来越强大,查询缓存可能是一个影响服务器

查询表达式和LINQ to Objects

查询表达式实际上是由编译器“预处理”为“普通”的C#代码,接着以完全普通的方式进行编译.这种巧妙的发式将查询集合到了语言中,而无须把语义改得乱七八糟 LINQ的介绍 LINQ中的基础概念 降低两种数据模型之间的阻抗失配过程中,遇到的一个问题就是,通常会涉及创建另一个模型来作为桥梁 序列 它通过IEnumerable和IEnumerable<T>接口进行封装 序列和其他集合数据结构最大的区别:当你从序列读取数据的时候,通常不知道还有多少数据项等待读取,或者不能访问任意的数据项——只能是当前这个

闭包在.NET下的实现(编译器玩的小把戏)-----C#本质论读书笔记

参加工作以来,拜读过很多大作.有好多书读的时候感觉大彻大悟,不自觉的发出‘哦...’这样的感叹.但是随着杀猪刀(时间)不断的飞逝,不仅给我脸上带来了皱纹,还带走了不少前人总结和归纳的知识点和那些我还没来得及吸收的宝贵财富.好记性不如烂笔头,我决定开始写一些读书的笔记和工作上的心得,最好是两者能够结合起来,把知识真正的自己转化成自己的能力. 下面进入正题.闭包在程序员的日常工作几乎无所不在,当然不仅是工作,面试的时候经常也会有相关的题目.看过很多博客园上的朋友都有解释,每次重温都有‘哦...’的感

Programming in Scala (Second Edition) 读书笔记15 case class and pattern matching

一个算术表达式包含: 数字,变量,二元操作符,一元操作符.用下面几个类来模拟它们 package chapter15 abstract class Expr case class Var(name: String) extends Expr case class Number(num: Double) extends Expr case class UnOp(operator: String, arg: Expr) extends Expr case class BinOp(operator: 

《C++ Primer》读书笔记—第四章 表达式

声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程 1.表达式由一个或多个运算对象组成,对表达式求值将得到一个结果.字面值和变量是最简单的表达式,其结果就是字面值和变量的值.把一个运算符和一个或多个运算对象组合起来可以生成复杂的表达式. 2.指针不能转换成浮点数. 3.一个左值表达式的求职结果是一个对象或者一个函数,然而以常量对象为代表的某些左值实际上不能作为赋值语句的左侧运算对象. 4.在除法运算中,如果两个运

《高性能MySQL》读书笔记--查询性能优化

对于高性能数据库操作,只靠设计最优的库表结构.建立最好的索引是不够的,还需要合理的设计查询.如果查询写得很糟糕,即使库表结构再合理.索引再合适,也无法实现高性能.查询优化.索引优化.库表结构优化需要齐头并进,一个不落. 6.1 为什么查询速度会慢 通常来说,查询的生命周期大致可以按照顺序来看:从客户端>>服务器>>在服务器上进行解析>>生成执行计划>>执行>>返回结果给客户端.其中执行可以认为是整个生命周期中最重要的阶段,这其中包括了大量为了检索