博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
阅读量:5308 次
发布时间:2019-06-14

本文共 2191 字,大约阅读时间需要 7 分钟。

Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析

一:Linq的聚合运算

1. 常见的聚合运算:Aggregate,Count, Sum, Distinct,Max,Min

这几个聚合运算,我们在sql中看的还是比较多的。

二:Count

1. 这个我们用到的非常多,Count() / LongCount().

2. LongCount每次都是foreach循环,所以这个性能问题就出来了。

三:Sum

var nums = new int[] { 10, 20, 30, 40, 50, 60 };

var query = nums.Sum(i => (long)i);

我们最好看一下源代码,这样方便我们了解代码的性能问题,这样可以做到心中有数。

public static decimal Sum(this IEnumerable<decimal> source)

{
if (source == null)
{
throw Error.ArgumentNull("source");
}
decimal num = 0m;
foreach (decimal current in source)
{
num += current;
}
return num;
}

可以看到,其实就是一个简单的foreach。

四:Distinct

我想大家有非常清楚,它是一个去重。

static void Main(string[] args)

{
var nums = new int[] { 10, 20, 10, 40, 20, 30 };

var query = nums.Distinct();

}

源码探究:

private static IEnumerable<TSource> DistinctIterator<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)

{
Enumerable.<DistinctIterator>d__63<TSource> expr_07 = new Enumerable.<DistinctIterator>d__63<TSource>(-2);
expr_07.<>3__source = source;
expr_07.<>3__comparer = comparer;
return expr_07;
}

一定要清楚,又是一个枚举类【<DistinctIterator>d__63`1】

可以看到,所谓的去重,就是将集合的数字添加到System.Linq.Set集合中,这个Set一看就是HashSet,对不对。。。

IL_005b: callvirt instance bool class System.Linq.Set`1<!TSource>::Add(!0)

五:Aggregate

相对来说是最复杂的,它就是一个累加器,就是对集合中的每一次数组执行一个func函数,其中有一个累加值,有一个当前值。

我们可以用Aggregate做一个Sum的操作。

static void Main(string[] args)
{
var nums = new int[] { 10, 20, 10, 40, 20, 30 };

var list = nums.Aggregate((total, next) =>

{
return total + next;
});
}

Aggregate的源码分析:

public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)

{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (func == null)
{
throw Error.ArgumentNull("func");
}
TSource result;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (!enumerator.MoveNext()) //获取第一个current值。
{
throw Error.NoElements();
}
TSource tSource = enumerator.Current; //将第一个值作为全局变量。
while (enumerator.MoveNext()) //取当前的source的第二个值。
{
tSource = func(tSource, enumerator.Current); //然后将第一个值和第二个值调用func委托。
//取得的值放到全局变量tSource中。
}
result = tSource;
}
return result;
}

六: Max,Min 函数

学过sql都明白。

 

转载于:https://www.cnblogs.com/dragon-L/p/6486851.html

你可能感兴趣的文章
移动设备和SharePoint 2013 - 第3部分:推送通知
查看>>
SOPC Builder中SystemID
查看>>
MySQL数据库备份工具mysqldump的使用(转)
查看>>
青海行--(7月19日)麦积山石窟
查看>>
NTP服务器配置
查看>>
【转】OO无双的blocking/non-blocking执行时刻
查看>>
深入理解java集合框架(jdk1.6源码)
查看>>
php截取后台登陆密码的代码
查看>>
选假球的故事
查看>>
ul li剧中对齐
查看>>
关于 linux 的 limit 的设置
查看>>
模块搜索路径
查看>>
如何成为一名优秀的程序员?
查看>>
HDU(4528),BFS,2013腾讯编程马拉松初赛第五场(3月25日)
查看>>
C++期中考试
查看>>
Working with Characters and Strings(Chapter 2 of Windows Via C/C++)
查看>>
vim中文帮助教程
查看>>
Android 创建与解析XML(四)—— Pull方式
查看>>
CodeForces 411B 手速题
查看>>
同比和环比
查看>>