
定义
Aggregate扩展方法旨在对序列应用进行累加,它一共包含了3个重载方法,如下:
| 方法定义 | 方法说明 |
|---|---|
| Aggregate |
对序列应用累加器函数。 |
| Aggregate |
对序列应用累加器函数。 将指定的种子值用作累加器初始值。 |
| Aggregate |
对序列应用累加器函数。 将指定的种子值用作累加器的初始值,并使用指定的函数选择结果值。 |
Aggregate(IEnumerable, Func)
public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func){if (source == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);}if (func == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.func);}//获取泛型版本的迭代器using (IEnumerator<TSource> e = source.GetEnumerator()){//判断第一个值是否存在if (!e.MoveNext()){ThrowHelper.ThrowNoElementsException();}//将第一个值赋予resultTSource result = e.Current;//循环处理while (e.MoveNext()){//第一次调用func时: 第一个参数是集合的第一个值,第二个参数是集合的第二个值//第二次调用func时: 第一个参数是上一次func返回的值,第二个参数是集合的第三个值//......//第n次调用func时: 第一个参数依然是上一次func返回的值,第二个参数是集合的第n+1个值result = func(result, e.Current);}//如果集合只有一个元素,直接返回第一个值//如果集合超过一个元素,按上面的逻辑依次调用func后返回的最终值return result;}}
//示例1string[] strs = new string[] { "I","am","happy","to","share" };string sentence = strs.Aggregate((str1, str2) => str1 + " " + str2);//output: I am happy to share//示例2int[] nums = new int[] { 1,2,3,4,5 };int count = nums.Aggregate((num1, num2) => num1 + num2);//output: 15
Aggregate(IEnumerable, TAccumulate, Func)
public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func){if (source == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);}if (func == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.func);}TAccumulate result = seed;foreach (TSource element in source){//第一次调用func时: 第一个参数是seed参数,第二个参数是集合的第一个值//第二次调用func时: 第一个参数是上一次func返回的值,第二个参数是集合的第二个值//......//第n次调用func时: 第一个参数依然是上一次func返回的值,第二个参数是集合的第n个值result = func(result, element);}return result;}
/// <summary>/// 定义一个类,包含花费的日期和购物花费、房租/// </summary>public class Expenses{/// <summary>/// 日期/// </summary>public DateOnly Date { get; set; }/// <summary>/// 购物花费/// </summary>public decimal Shopping { get; set; }/// <summary>/// 房租/// </summary>public decimal Rent { get; set; }}//初始化一些数据List<Expenses> expenses = new List<Expenses>(){new Expenses(){ Date = DateOnly.Parse("2023-03-29"), Shopping = 50, Rent = 0 },new Expenses(){ Date = DateOnly.Parse("2023-03-30"), Shopping = 60, Rent = 0 },new Expenses(){ Date = DateOnly.Parse("2023-03-31"), Shopping = 70, Rent = 1500 },};//此时我们想求出这三天每样花费的总计{//申明一个匿名变量,因为第一个传入的参数类型也是func的返回类型,所以我们都用decimalvar expenseCount = new { shopping = (decimal)0, rent = (decimal)0 };//累加Shopping和RentexpenseCount = expenses.Aggregate(expenseCount,(expense1, expense2) =>new {shopping = expense1.shopping + expense2.Shopping,rent = expense1.rent + expense2.Rent});//expenseCount:{"shopping":180,"rent":1500}}//当然,我们也可以实例化一个Expenses,循环执行方法的时候在里面属性直接叠加//这样我们都不需要返回值了,因为返回值就是expenseCount本身{var expenseCount = new Expenses();expenseCount = expenses.Aggregate(expenseCount,(expense1, expense2) =>{expense1.Shopping += expense2.Shopping;expense1.Rent += expense2.Rent;return expense1;});//expenseCount: {"Date":"0001-01-01","Shopping":180,"Rent":1500}}
Aggregate(IEnumerable, TAccumulate, Func, Func)
public static TResult Aggregate<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector){if (source == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);}if (func == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.func);}if (resultSelector == null){ThrowHelper.ThrowArgumentNullException(ExceptionArgument.resultSelector);}TAccumulate result = seed;foreach (TSource element in source){//第一次调用func时: 第一个参数是seed参数,第二个参数是集合的第一个值//第二次调用func时: 第一个参数是上一次func返回的值,第二个参数是集合的第二个值//......//第n次调用func时: 第一个参数依然是上一次func返回的值,第二个参数是集合的第n个值result = func(result, element);}//其实就是再对结果进行处理return resultSelector(result);}
//上一个示例的基础上我们想得到这三天总计的花费var expenseCount = new Expenses();decimal count = expenses.Aggregate(expenseCount,(expense1, expense2) =>{expense1.Shopping += expense2.Shopping;expense1.Rent += expense2.Rent;return expense1;},ec => ec.Shopping+ec.Rent);//ec其实就代表了叠加到最后的expenseCount//count: 1680
