首页 > Windows开发 > 详细

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

时间:2016-11-21 12:04:05      阅读:319      评论:0      收藏:0      [点我收藏+]

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

 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.   
  6.  static void List1(string rootDirectory, string searchPattern)  
  7.  {  
  8.      IEnumerable<FileInfo> files =  
  9.          from fileName in Directory.GetFiles(  
  10.              rootDirectory, searchPattern)  
  11.          select new FileInfo(fileName);  
  12.   
  13.      foreach (FileInfo file in files)  
  14.      {  
  15.          Console.WriteLine(".{0} ({1})",  
  16.              file.Name, file.LastWriteTime);  
  17.      }  
  18.  }  
 
技术分享
 这里返回的是一个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.   
  6. static void ListByFileSize2(  
  7.         string rootDirectory, string searchPattern)  
  8. {  
  9.     IEnumerable<FileInfo> files =  
  10.         from fileName in Directory.GetFiles(  
  11.             rootDirectory, searchPattern)  
  12.         orderby new FileInfo(fileName).Length, fileName  
  13.         select new FileInfo(fileName);  
  14.   
  15.     foreach (FileInfo file in files)  
  16.     {  
  17.         //  As simplification, current directory is  
  18.         //  assumed to be a subdirectory of  
  19.         //  rootDirectory  
  20.         string relativePath = file.FullName.Substring(  
  21.             Environment.CurrentDirectory.Length);  
  22.         Console.WriteLine(".{0}({1})",  
  23.             relativePath, file.Length);  
  24.     }  
  25. }  

可以用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.   
  7.     foreach (IGrouping<bool, string> wordGroup  
  8.         in selection)  
  9.     {  
  10.         Console.WriteLine(Environment.NewLine + "{0}:",  
  11.             wordGroup.Key ?  
  12.                 "Contextual Keywords" : "Keywords");  
  13.         foreach (string keyword in wordGroup)  
  14.         {  
  15.             Console.Write(" " +  
  16.                 (wordGroup.Key ?  
  17.                     keyword.Replace("*", null) : keyword));  
  18.         }  
  19.     }  
  20. }  

技术分享
 
结果 :
技术分享

 查询结果是一系列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.   
  7.     var selection = from groups in keywordGroups  
  8.                     select new  
  9.                     {  
  10.                         IsContextualKeyword = groups.Key,  
  11.                         Items = groups  
  12.                     };  
  13.   
  14.     foreach (var wordGroup in selection)  
  15.     {  
  16.         Console.WriteLine(Environment.NewLine + "{0}:",  
  17.             wordGroup.IsContextualKeyword ?  
  18.                 "Contextual Keywords" : "Keywords");  
  19.         foreach (var keyword in wordGroup.Items)  
  20.         {  
  21.             Console.Write(" " +  
  22.                 keyword.Replace("*", null));  
  23.         }  
  24.     }  
  25. }  

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

15.1.6 使用into进行查询延续





































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

原文:http://www.cnblogs.com/tangge/p/6084871.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!