手机网站关键词seo,网络推广工作具体需要做些什么,wordpress更改数据库,微信公众号管理平台登录前言在Dotnet开发过程中#xff0c;Aggregate作为IEnumerable的扩展方法#xff0c;十分常用。本文对Aggregate方法的关键源码进行简要分析#xff0c;以方便大家日后更好的使用该方法。使用Aggregate是对序列应用累加器的函数。看下面一段代码:Liststring lst new… 前言在Dotnet开发过程中Aggregate作为IEnumerable的扩展方法十分常用。本文对Aggregate方法的关键源码进行简要分析以方便大家日后更好的使用该方法。使用Aggregate是对序列应用累加器的函数。看下面一段代码:Liststring lst new Liststring() { 张三, 李四, 王麻子 };给了我们这样的一个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 AggregateTSource(this IEnumerableTSource source, FuncTSource, TSource, TSource func)FuncTSource, TSource, TSource func 可以看出方法接收一个委托该委托接收两个TSource类型的参数第一个参数是记录值第二个参数是从IEnumerable中取下一个元素最后一个是返回累加器的最终值。可能有人对前面的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的原型一样我们来一步一步的实现它。我们声明一个MyAggregatepublic static TSource MyAggregateTSource(this IEnumerableTSource source, FuncTSource, TSource, TSource func)我们来一步一步的实现它的源码我们方法内部肯定是要对参数进行判空校验的public static TSource MyAggregateTSource(this IEnumerableTSource source, FuncTSource, TSource, TSource func)
{if (source null){throw new Exception(source is null);}if (func null){throw new Exception(func is null);}
}扩展方法是静态类的静态方法其实第一个参数用this修饰符代表源元素的类型且是一个可进行迭代的源元素类型this IEnumerableTSource source那么我们就知道这个源元素是一个 可以获得循环访问集合的枚举器那么我们就可以使用GetEnumerator这个方法进行迭代了虽然我们对源元素进行了判空我们程序为了严谨性我们肯定要对源元素里面是否有内容进行判空using (IEnumeratorTSource enumerator source.GetEnumerator()){if (!enumerator.MoveNext()){throw new Exception(enumerator is null);}}然后我们声明一个返回的类型接收当前值然后使用while循环遍历源元素的值最后返回值这样我们的Aggregate源码就实现了public static TSource MyAggregateTSource(this IEnumerableTSource source, FuncTSource, TSource, TSource func){if (source null){throw new Exception(source is null);}if (func null){throw new Exception(func is null);}using (IEnumeratorTSource enumerator source.GetEnumerator()){if (!enumerator.MoveNext()){throw new Exception(enumerator is null);}TSource val enumerator.Current;while (enumerator.MoveNext()){val func(val, enumerator.Current);}return val;}}我们的Aggregate是有三个重载方法的我们实现了最简单的一个那我们来看第二个public static TAccumulate AggregateTSource, TAccumulate(this IEnumerableTSource source, TAccumulate seed, FuncTAccumulate, TSource, TAccumulate func就比第一个方法多了Accumulate seed 将指定的种子值用作累加器初始值。然后我们能使用这个方法str lst.Aggregate(我的输出结果, (first, second) ${first} 哈哈哈 {second} );Console.WriteLine(str);那怎么去理解这个将指定的种子值用作累加器初始值下面的这段代码和上面等同str 我的输出结果lst.Aggregate( (first, second) ${first} 哈哈哈 {second} );Console.WriteLine(str);我们就可以实现该源码了,由于我们初始值有了所以不用对元素里面是否有内容进行判空直接使用foreach遍历public static TAccumulate AggregateTSource, TAccumulate(this IEnumerableTSource source, TAccumulate seed, FuncTAccumulate, TSource, TAccumulate func){if (source null){throw Error.ArgumentNull(source);}if (func null){throw Error.ArgumentNull(func);}TAccumulate val seed;foreach (TSource item in source){val func(val, item);}return val;那我们再来看第三个public static TResult AggregateTSource, TAccumulate, TResult(this IEnumerableTSource source, TAccumulate seed, FuncTAccumulate, TSource, TAccumulate func, FuncTAccumulate, TResult resultSelector)对序列应用累加器函数。将指定的种子值用作累加器的初始值并使用指定的函数处理结果值。比第二个方法多了一个委托FuncTAccumulate, TResult resultSelector然后我们来使用该方法str lst.Aggregate(我的输出结果,(first, second) ${first} 哈哈哈 {second} ,end end 我是尾巴);然后我们来转换一下方便大家理解,str (lst.Aggregate(我的输出结果,(first, second) ${first} 哈哈哈 {second} )) 我是尾巴;为什么我这里加了一个大括号因为后面这个委托是对结果值进行一个整体处理可能这样举例不太恰当如果我们返回的结果是小写字母。我们就可以对整体结果进行一个小写转大写的操作这样可能理解就更深刻了str lst.Aggregate(我的输出结果,(first, second) ${first} 哈哈哈 {second} ,end end.ToUpper());str (lst.Aggregate(我的输出结果,(first, second) ${first} 哈哈哈 {second} )).ToUpper();然后它的源码实现也比较简单了,就比第二个方法多了一个对结果值的处理,修改一下上面的源码public static TResult AggregateTSource, TAccumulate, TResult(this IEnumerableTSource source, TAccumulate seed, FuncTAccumulate, TSource, TAccumulate func, FuncTAccumulate, TResult resultSelector){if (source null){throw Error.ArgumentNull(source);}if (func null){throw Error.ArgumentNull(func);}if (resultSelector null){throw Error.ArgumentNull(resultSelector);}TAccumulate val seed;foreach (TSource item in source){val func(val, item);}return resultSelector(val);}我们发现Aggregate只实现了Aggregate(IEnumerable, FuncTSource,TSource,TSource) 对序列应用累加器函数。AggregateTSource,TAccumulate(IEnumerable, TAccumulate, FuncTAccumulate,TSource,TAccumulate) 对序列应用累加器函数。将指定的种子值用作累加器初始值。AggregateTSource,TAccumulate,TResult(IEnumerable, TAccumulate, FuncTAccumulate,TSource,TAccumulate, FuncTAccumulate,TResult)对序列应用累加器函数。将指定的种子值用作累加器的初始值并使用指定的函数选择结果值并没有实现 :对序列应用累加器函数不使用指定种子的累加器初始值且使用指定的函数选择结果值。那看了我的源码解析是不是很容易实现了public static TResult MyAggregateTSource, TResult(this IEnumerableTSource source, FuncTSource, TSource, TSource func, FuncTSource, TResult resultSelector){if (source null){throw new Exception(source is null);}if (func null){throw new Exception(func is null);}using (IEnumeratorTSource enumerator source.GetEnumerator()){if (!enumerator.MoveNext()){throw new Exception(enumerator is null);}TSource val enumerator.Current;while (enumerator.MoveNext()){val func(val, enumerator.Current);}return resultSelector(val);}}如果还不明白对序列应用累加器函数。并使用指定的函数选择结果值建议大家再看一遍.最后大家如果喜欢我的文章还麻烦给个关注并点个赞, 希望net生态圈越来越好