Using Enumerable.Aggregate(...) Method over an empty sequence

aggregate, c#, linq, sequence

Solution

To concatenate a list of strings, use the `string.Join` method.

The `Aggregate` function doesn't work with empty collections. It requires a binary accumulate function and it needs an item in the collection to pass to the binary function as a seed value.

However, there is an overload of `Aggregate`:

public static TResult Aggregate<TSource, TAccumulate, TResult>(
    this IEnumerable<TSource> source,
    TAccumulate seed,
    Func<TAccumulate, TSource, TAccumulate> func,
    Func<TAccumulate, TResult> resultSelector
)

This overload allows you to specify a seed value. If a seed value is specified, it will also be used as the result if the collection is empty.

EDIT: If you'd really want to use `Aggregate`, you can do it this way:

sequence.Aggregate(string.Empty, (x, y) => x == string.Empty ? y : x + Separator + y)

Or this way by using `StringBuilder`:

sequence.Aggregate(new StringBuilder(), (sb, x) => (sb.Length == 0 ? sb : sb.Append(Separator)).Append(x)).ToString()

Problem

I would like to use the Enumerable.Aggregate(...) method to concatenate a list of strings separated by a semicolon. Rather easy, isn't it? Considering the following: - `private const string LISTSEPARATOR = "; ";` - album.OrderedTracks is `List<TrackDetails>` - TrackDetails has DiscNumber Int16? property The following statement will trow an exception if the sequence returned by Distinct() is empty (as the Aggregate() method doesn't apply on empty sequence): ``` txtDiscNumber.Text = album.OrderedTracks .Where(a => a.DiscNumber.HasValue) .Select(a => a.DiscNumber.Value.ToString()) .Distinct() .Aggregate((i, j) => i + LISTSEPARATOR + j); ``` The workaround I am using: ``` List<string> DiscNumbers = album.OrderedTracks .Where(a => a.DiscNumber.HasValue) .Select(a => a.DiscNumber.Value.ToString()) .Distinct() .ToList(); if (!DiscNumbers.Any()) txtDiscNumber.Text = null; else txtDiscNumber.Text = DiscNumbers.Aggregate((i, j) => i + LISTSEPARATOR + j); ``` Is there any better solution? Is it possible to do this in a single LINQ statement? Thanks in advance.

Original source