How it works
Aggregate repeatedly combines an accumulated state with the next sequence element. The overload with a seed supplies the starting state explicitly. This makes the empty-input behavior clear: if no elements are processed, the seed itself is returned. A fold can calculate more than one property when the accumulator is a tuple or another summary value.
Choose an operation whose state transitions are easy to explain. A simple Sum or Count is usually clearer than an elaborate Aggregate call that only recreates those operations. Aggregate becomes useful when one pass deliberately computes a related set of results, or when the domain has a specific combination rule that is clearer as an accumulator update.
Walk through the example. The accumulator begins with a count of zero and total of zero. Each integer increments the count and adds to the total, producing three values and a total of twelve. Running the same fold on an empty array returns the unchanged seed. The example prints both fields so the empty-input contract can be compared directly with the nonempty case.
Watch the boundary. The seedless overload has a different empty-sequence contract and cannot return a normal result when no initial element exists. Do not switch overloads casually while refactoring. Also avoid mutating shared objects inside an accumulator unless that ownership is explicit. A fresh immutable value on each step is often easier to reason about in a teaching example and in small report calculations.
Practice independently. Fold a sequence of signed adjustments into a tuple containing positive count, negative count, and net total. Define how zero affects the counts. Test an empty batch, all zeros, and a mixture of signs. Compare the result with three separate straightforward calculations, then decide whether one fold is clearer for the actual workflow rather than assuming fewer passes always means a better design.
A working example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
(int Count, int Total) Summarize(IEnumerable<int> values) =>
values.Aggregate((Count: 0, Total: 0), (state, value) => (state.Count + 1, state.Total + value));
var full = Summarize(new[] { 3, 4, 5 });
var empty = Summarize(Array.Empty<int>());
Console.WriteLine($"{full.Count}:{full.Total}");
Console.WriteLine($"{empty.Count}:{empty.Total}");
Expected output
3:12 0:0
The seed is both the starting state and the result for an empty input.