专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »DotNet » 正则表达式:Query Expressions(查询表达式) »正文

正则表达式:Query Expressions(查询表达式)

来源: 发布时间:星期四, 2009年2月12日 浏览:199次 评论:0


查询表达式提供了和SQL这样关系化和分级查询语言相类似语言集成语法个查询表达式是以from子句开头以select或者group子句结束这个from子句可以在其后跟随任意多个from、let、where或者join子句

那么查询表达式中这些子句都是做什么呢?from子句是个引入了个覆盖整个序列范围变量生成器;let子句计算个值并传入个标识符来显示这个值;where子句是个从结果集中排除元素过滤器;join子句用于比对源序列和另个序列中指定键并找出匹配对;select或group子句根据范围变量来指定结果形式;o子句可以将个查询结果作为后续查询中生成器并以此来拼接两个查询

前面提到了每条查询语句都必须是以from开头在from后面可以接除“;”、“,”和“=”以外所有符号如果要在查询语句中使用这些标识符需要在前面加上“@”符号

C# 3.0并没有给查询表达式指定明确执行语义准确地说C# 3.0把查询语句翻译为对依附于查询表达式模式思路方法这些思路方法可以是对象例子思路方法也可以是扩展思路方法它们执行才是实际查询工作查询表达式翻译为思路方法过程是发生在类型绑定或者过载抉择的前句法映射过程翻译可以保证语法正确但不能确保生成定是语法正确C#代码在翻译的后作为结果思路方法会被作为思路方法并且这可能会依次找出例如思路方法不存在、参数中存在类型或者对范型思路方法类型推断失败的类

条查询语句执行是以重复地应用后续翻译直到不再有更深层可进行缩减这些翻译根据优先权排列每个部分都假定前部分中翻译已经被完全地执行明确翻译采用透明标志符(Transparent identiers)“*”来注入范围变量

接下来我们还是来看码说话吧这样可能更便于理解和掌握前面提到查询表达式并不具备确切执行语义而是用来被翻译成采用查询表达式模式思路方法那我们就来看看这里所说翻译到底是什么样子

1: public void Query 2: { 3: Dictionary<, > students = Dictionary<, >; 4: students.Add("ZeroCool", 24); 5: students.Add("Michael", 21); 6: students.Add("Frieda", 22); 7: 8: IEnumerable<KeyValuePair<, >> queryResult = from student in students 9: where student.Value <= 23 10: orderby student.Value descending 11: select student; 12: 13: foreach (var student in queryResult) 14: { 15: Console.WriteLine(student.Key + " is " + student.Value + " years old."); 16: } 17: 18: Console.ReadLine; 19: }
上面这段代码要做事情是从students这个集合里面找出所有年龄小于24岁学生并按年龄降序排序我们着重来看下第8到第11行代码我想所有写过SQL查询语句朋友都会对这句话感到似曾相识它非常像SQL查询语句但又略有差别我们来看下这句话会被C# 3.0翻译成怎样思路方法就会了解它是如何工作

1: IEnumerable<KeyValuePair<, >> queryResult 2: = students.Where(student => student.Value <= 23).OrderByDescending(student => student.Value).Select(student => student);
上面这行代码就是查询语句翻译结果这行代码放在原先中替换掉第8到第11行代码依然是可以得出同样结果或许这看上去还不太好理解吧那么我们用先前介绍过表达式树来翻译

1: Func<KeyValuePair<, >, bool> filter = student => student.Value <= 23; 2: Func<KeyValuePair<, >, > extract = student => student.Value; 3: Func<KeyValuePair<, >, KeyValuePair<, >> result = student => student; 4: 5: IEnumerable<KeyValuePair<, >> queryResult = students.Where(filter).OrderByDescending(extract).Select(result);
这样虽然代码量多了确理解起来方便了很多翻译结果是直接原数据集合对象Where思路方法选出符合条件候选项然后在用OrderByDescending思路方法进行降序排序最后通过Select思路方法把这些结果返回回来上面例子虽然比较简单但是可以让我们很好地了解查询表达式语法以及翻译方式只要我们了解了最基本也是最核心概念那么即使面对复杂查询表达式也可以迎刃而解了

前面提到过个概念叫做“透明标识符”可能其定义比较抽象大家不太好理解现在我们借助个翻译过程来解释下到底什么事透明标识符吧

1: from customer in customers 2: from order in customer.Orders 3: orderby order.Total descending 4: select { customer.Name, order.Total };
我们假设有上面这句查询语句工作是从消费者集合里找出每个消费者名字和他订购总量并按照每个消费者订购总量对他们进行降序排序接下来我们来看看这句查询表达式将会被翻译成什么样子把

1: from * in 2: from customer in customers 3: from order in customer.Orders 4: select { customer, order } 5: orderby order.Total descending 6: select { customer.Name, order.Total }
现在透明标识符*已经出现了不过这还只是中间步骤我们继续往下翻译:

1: customers. 2: SelectMany(customer => customer.Orders.Select(order => { customer, order })). 3: OrderByDescending(* => order.Total).Select(* => { customer.Name, order.Total })
如果我们把透明标识符去掉那么上面几行代码就等效于:

1: customers. 2: SelectMany(customer => customer.Orders.Select(o => { customer, order })). 3: OrderByDescending(x => x.order.Total).Select(x => { x.customer.Name, x.order.Total })


其中x是编译器生成个开发人员看不见摸不着标识符透明标识符不是个确切语言特性它只作为查询表达式翻译过程中个中间步骤

当查询表达式注入个透明标识符时接下来翻译步骤会将这个透明标识符传入到Lambda表达式和匿名对象器中去在这样上下文中透明标识符具有以下行为:

个透明标识符作为Lambda表达式中参数出现时候相关联匿名类型成员将自动处于Lambda表达式体中范围内;
个含有透明标识符成员处于当前范围内那么这个成员成员也都处于当前范围内;
个透明标识符作为个匿名对象器中成员声明符出现时它会引入个带有透明标识符成员;
好了查询表达式就介绍到这里吧也许你觉得查询表达式有很多概念读起来比较抽象不那么便于理解但是我相信只要你动手多练习很多概念都能很好地理解C# 3.0 探索的旅系列技术介绍文章也就到此为止了我相信C# 3.0为我们广大开发人员带来这些新特性都能够是我们在很大程度上提高开发效率同时也增加了很多开发乐趣随着微软不断有面向各个层面和领域新技术问世我相信.NET平台也会逐渐成为个更加广泛、强大技术平台接下来时间我会和大家起共同探讨下微软个重头戏——LINQ项目敬请关注!
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: