写点什么

VB 和 C#中的 LINQ 聚合

  • 2007-09-18
  • 本文字数:1954 字

    阅读完需:约 6 分钟

Aggregate 是一个可以从一个数据集合中获取标量值的函数,比如 T-SQL 中的 Min()、Max() 和 Sum() 等。现在 VB 和 C#也都对这种聚合的功能给于了支持,但是是以一种非常不同的方式。

VB 和 C#都是以扩展方法的形式支持聚合的。在一个 IEnumberable 对象中,一个简单的调用是通过点符号完成的,比如:

<pre dir="ltr"><p dir="ltr">var totalVirtualMemory = <br></br> (from p in Process.GetProcesses() </p><p dir="ltr"> select p.VirtualMemorySize64).Sum();</p><p>Dim totalVirtualMemory = _</p><br></br> (From p In Process.GetProcesses _<br></br> Select p.VirtualMemorySize64).Sum从这儿可以看到,VB 和 C#的版本几乎是一样的。但 VB 还为聚合专门提供了一个 LINQ 语法:

<pre dir="ltr"><p dir="ltr">Dim totalVirtualMemory = Aggregate p In Process.GetProcesses _ </p><p dir="ltr"> Into p.VirtualMemorySize64</p>如果这是二者之间唯一区别的话,那么也就没有什么好谈的了。但是,有趣的事情发生在当你想同时操作不止一个“列”的时候。简便起见,我们假设要操作正在使用的全部虚拟内存和全部工作集(物理内存)。

使用匿名类,我们可以轻松地创建一个带有它们两个值的变量。

<pre dir="ltr"><p dir="ltr">var totals = new <br></br>{ <br></br> totalVirtualMemory = (from p in Process.GetProcesses() </p><p dir="ltr"> select p.VirtualMemorySize64).Sum(), <br></br> totalWorkingSet = (from p in Process.GetProcesses() </p><p dir="ltr"> select p.WorkingSet64).Sum() <br></br>};</p>这儿的问题是 GetProcesses() 被调用了两次。也就是说操作系统必须查询两次,在结果集合中执行两次循环。一个更快的方法也许是对 GetProcesses() 的调用进行缓存。

<pre dir="ltr"><p dir="ltr">var processes = (from p in Process.GetProcesses() <br></br> select new { p.VirtualMemorySize64, p.WorkingSet64 }</p><p dir="ltr"> ).ToList();</p><p dir="ltr"><br></br>var totals2 = new <br></br>{ <br></br> totalVirtualMemory = (from p in processes <br></br> select p.VirtualMemorySize64).Sum(), <br></br> totalWorkingSet = (from p in processes <br></br> select p.WorkingSet64).Sum() <br></br>};</p>虽然好了一些,但仍然需要两次循环。如何只执行一次呢?这时我们需要一个定制的聚合器,和一个保存这些结果的命名类(Named Class)。

<pre dir="ltr"><p dir="ltr">public static ProcessTotals Sum(this IEnumerable source) <br></br>{ <br></br> var totals = new ProcessTotals(); <br></br> foreach (var p in source){ <br></br> totals.VirtualMemorySize64 += p.VirtualMemorySize64; <br></br> totals.WorkingSet64 += p.WorkingSet64; <br></br> } <br></br> return totals; <br></br>} </p><p>public class ProcessTotals </p><br></br>{ <br></br> public long VirtualMemorySize64 { get; set; } <br></br> public long WorkingSet64 { get; set; } <br></br>} <p>var totals3 = (from p in Process.GetProcesses() select p).Sum();</p>开发者在 Visual Basic 中也可以这样做,但需要像下面这样做:

<pre dir="ltr"><p dir="ltr">Dim totals3 = Aggregate p In Process.GetProcesses _ <br></br> Into virtualMemory = Sum(p.VirtualMemorySize64), _<br></br> workingSet = Sum(p.WorkingSet64)</p>就像在上一个 C#例子中,我们是用一个含有两个 Field 的变量解决问题的。但这和 C#的例子不一样,你不会因为是选择创建自己的聚合函数及类还是在遍历集合中浪费两次循环,而左右为难。

公平起见,C#确实还有那么几招。不像 VB 那样只支持单行的匿名函数,只要需要,C#可以让它们很复杂,这就使得它可以在需要的时候创建匿名的聚合函数。

<pre dir="ltr"><p dir="ltr">var processes = <br></br> (from p in Process.GetProcesses() <br></br> select new { p.VirtualMemorySize64, p.WorkingSet64 }); <br></br>var totals4 = processes.Aggregate(new ProcessTotals(), (sum, p) => <br></br> { <br></br> sum.WorkingSet64 += p.WorkingSet64; <br></br> sum.VirtualMemorySize64 += p.VirtualMemorySize64; <br></br> return sum;</p><p dir="ltr"> });</p>注意在这儿,ProcessTotals 类依然需要用到。匿名类不能被用在这儿,因为 C#匿名类是不可变的。虽然 Visual Basic 的匿名类可以改变,但是在这儿也没用,因为 VB 不能创建多行的匿名函数。

但是 Visual Basic 和 C#都较从前有了强有力的改进,双方也各有长处,让对方在不足之处加油赶上。

查看英文原文: LINQ Aggregates in VB and C#

2007-09-18 04:261238

评论

发布
暂无评论
发现更多内容

字典树之旅02.Trie 的标准实现

极客志

自然语言处理 数据结构 算法 Trie 字典树

Redis为何这么快?

JavaEdge

12月日更

SQS 和 SNS 对比分析

liuzhen007

28天写作 12月日更

[Pulsar] Consumer如何消费消息

Zike Yang

Apache Pulsar 12月日更

聊聊 Kafka:Producer 源码解析

老周聊架构

字典树之旅01.开篇

极客志

自然语言处理 数据结构 算法 nlp 字典树

技术人创业过程中应保持开放的心态

wood

创业 技术 28天写作

记录:今年最骄傲的一件事

将军-技术演讲力教练

盘点JavaScript哪些常用的字符串对象

你好bk

JavaScript 大前端 字符串 基础知识 12月日更

团队基建系列 - 组织知识传承3 破局

搬砖的周狮傅

跟老表学云服务器开发专栏导航

老表

Python 内容合集 签约计划第二季 技术专题合集 跟老表学云服务器

面试官synchronized连环问,学会Monitor之后轻松拿下

李子捌

Java、 28天写作 12月日更

你了解集合?那你倒是给我说说啊!【1】

XiaoLin_Java

12月日更

Prometheus Exporter (二十一)Ceph Exporter

耳东@Erdong

Prometheus Ceph 28天写作 exporter 12月日更

「架构实战营」模块一《为何架构设计能力难以提升》作业

DaiChen

作业 模块一 「架构实战营」

如何用Python发送告警通知到钉钉?

老表

Python Linux 守护进程 跟老表学云服务器

来来来,手摸手写一个hook

全栈潇晨

React React Hooks

学生管理系统架构设计

tony

「架构实战营」

在线MySQL,SQL Server建表语句生成JSON测试数据工具

入门小站

工具

一对一沟通有必要吗?

Justin

沟通 28天写作

面试官问我:什么是缓存击穿,该怎么解决?

喵叔

28天写作 12月日更

模块1

Geek_59dec2

架构实战营 第4期 模块一作业

架构实战营 模块一 「架构实战营」

Java jar 如何防止被反编译

xcbeyond

28天写作 12月日更

学习能力

Nydia

老大react说:schedule,我们今年的小目标是一个亿

全栈潇晨

React React Hooks

毕业总结

毛先生

架构训练营作业一

supermenG

架构师训练营 4 期

MySQL探秘(八):InnoDB的事务

程序员历小冰

MySQL 事务 28天写作 12月日更

聊聊IT行业的项目管理模式

圣迪

项目管理 敏捷 pmp 开发 瀑布

python scrapy极细拆解,打开Spider类看内容,顺手爬了一下优设网

梦想橡皮擦

12月日更

VB和C#中的LINQ聚合_.NET_Jonathan Allen_InfoQ精选文章