在Dotnet开发过程中,Aggregate作为IEnumerable的扩展方法,十分常用。本文对Aggregate方法的关键源码进行简要分析,以方便大家日后更好的使用该方法。
Aggregate是对序列应用累加器的函数。
看下面一段代码:
List lst = new List() { "张三", "李四", "王麻子" };
给了我们这样的一个list集合,我们想要得到
"张三 哈哈哈 李四 哈哈哈 王麻子 "
这样的一个结果;
假如我们没有linq,我们该怎么去写这个代码呢?
可能和下面这段代码没有多少出入!
string str = "";
for (int i = 0; i < lst.Count; i++)
{
str += lst[i] + " 哈哈哈 ";
}
Console.WriteLine(str);
那如果使用linq的扩展方法Aggregate就显得简单的多了
str = lst.Aggregate((first, second) => $"{first} 哈哈哈 {second} ");
那我肯定不只是给大家介绍这个东西怎么写的,我们是来刨析它的原理的。我们来看看他的原型
public static TSource Aggregate(this IEnumerable source, Func func)
Func
可能有人对前面的lambda怎么演变的不清楚
(first, second) => $"{first} 哈哈哈 {second} "
我这里再讲一下,具体的内容请看我的文章你真的了解Lambda表达式吗?
其实这个lambda表达式转换成方法就是这样的
public string MyAdd(string first, string second)
{
return $"{first} 哈哈哈 {second} " ;
}
然后这样去使用,输出的结果也是一样的
str = lst.Aggregate(MyAdd);
Console.WriteLine(str);
看到这里你可能还是很疑惑,那Aggregate内部的运行原理是怎样的呢?我们定义一个扩展方法跟Aggregate的原型一样我们来一步一步的实现它。我们声明一个MyAggregate
public static TSource MyAggregate(this IEnumerable source, Func func)
我们来一步一步的实现它的源码
我们方法内部肯定是要对参数进行判空校验的
public static TSource MyAggregate(this IEnumerable source, Func func)
{
if (source == null)
{
throw new Exception("source is null");
}
if (func == null)
{
throw new Exception("func is null");
}
}
扩展方法是静态类的静态方法,其实第一个参数用this修饰符代表源元素的类型,且是一个可进行迭代的源元素类型
this IEnumerable source
那么我们就知道这个源元素是一个 可以获得循环访问集合的枚举器那么我们就可以使用GetEnumerator这个方法进行迭代了,虽然我们对源元素进行了判空,我们程序为了严谨性,我们肯定要对源元素里面是否有内容进行判空
using (IEnumerator enumerator = source.GetEnumerator())
{