DAY 29
1
Software Development

原始碼分析

Source Code: Aggregate.cs

第一個方法

``````public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
{
if (source == null)
{
throw Error.ArgumentNull(nameof(source));
}

if (func == null)
{
throw Error.ArgumentNull(nameof(func));
}

using (IEnumerator<TSource> e = source.GetEnumerator())
{
if (!e.MoveNext())
{
throw Error.NoElements();
}

TSource result = e.Current;
while (e.MoveNext())
{
result = func(result, e.Current);
}

return result;
}
}
``````

• 檢查傳入參數(`source``func`)是否為空，如果為空則拋出`ArgumentNull`例外
• 通過參數檢查後，取得`Enumerator`(`GetEnumerator()`)開始巡覽
• 如果集合沒有元素，拋出`NoElements`例外
• 有元素的話將自己的數值丟給`func`，然後執行`func`
• 每次將`func`的結果傳給`result`，下一輪再丟進`func`
• 巡覽結束就傳回結果

第二個方法

``````public static TAccumulate Aggregate<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
{
if (source == null)
{
throw Error.ArgumentNull(nameof(source));
}

if (func == null)
{
throw Error.ArgumentNull(nameof(func));
}

TAccumulate result = seed;

foreach (TSource element in source)
{
result = func(result, element);
}

return result;
}
``````

• 第一個方法: `TSource result = e.Current;`
• 第二個方法: `TAccumulate result = seed;`

第三個方法

``````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)
{
throw Error.ArgumentNull(nameof(source));
}

if (func == null)
{
throw Error.ArgumentNull(nameof(func));
}

if (resultSelector == null)
{
throw Error.ArgumentNull(nameof(resultSelector));
}

TAccumulate result = seed;

foreach (TSource element in source)
{
result = func(result, element);
}

return resultSelector(result);
}
``````

• 第二個方法: `return result;`
• 第三個方法: `return resultSelector(result);`

測試案例賞析

Source Code: AggregateTests.cs

EmptySourceAndSeed

``````[Fact]
public void EmptySourceAndSeed()
{
int[] source = { };
long seed = 2;
long expected = 2;

Assert.Equal(expected, source.Aggregate(seed, (x, y) => x * y));
}
``````

`expected`會是2是因為`source`雖然是空陣列，但並不是`null`，所以不會拋出例外，再來就是`source`是空所以不會做巡覽，因此`seed`的值就會是回傳值。

dotnet/corefx