Making a list human-readable How is this function?

/// &lt;summary&gt;Extension methods used by RedViewerLibrary.&lt;/summary&gt;
internal static class Extensions
{
    /// &lt;summary&gt;A string array extension method that gets the human readable enumerated version of the array.&lt;/summary&gt;
    /// &lt;param name="items"&gt;The strings to act on.&lt;/param&gt;
    /// &lt;returns&gt;A string containing the enumerated results.&lt;/returns&gt;
    /// &lt;example&gt;null =&gt; ""&lt;/example&gt;
    /// &lt;example&gt;{} =&gt; ""&lt;/example&gt;
    /// &lt;example&gt;{"foo"} =&gt; "foo"&lt;/example&gt;
    /// &lt;example&gt;{"foo", "bar"} =&gt; "foo, and bar"&lt;/example&gt;
    /// &lt;example&gt;{"foo", "bar", "baz"} =&gt; "foo, bar, and baz"&lt;/example&gt;
    internal static string GetEnumerated(this string[] items)
    {
        if (items == null || items.Length == 0)
        {
            return string.Empty;
        }
        else if (items.Length == 1)
        {
            return items[0];
        }

        const string COMMA_SPACE = ", ";
        const string AND_STRING = "and ";

        var totalNamesLength = items.Aggregate(0, (oldValue, name) =&gt; name.Length + oldValue);
        var numberOfCommaSpaces = items.Length - 1;
        var commaSpacesLength = numberOfCommaSpaces * COMMA_SPACE.Length;
        var predictedLength = totalNamesLength + commaSpacesLength + AND_STRING.Length;
        var sb = new StringBuilder(predictedLength);

        int loopCount = items.Length - 1;
        sb.Append(items[0]);
        for (int idx = 1; idx != loopCount; ++idx)
        {
            sb.Append(COMMA_SPACE);
            sb.Append(items[idx]);
        }

        sb.Append(COMMA_SPACE);
        sb.Append(AND_STRING);
        sb.Append(items[items.Length - 1]);
        return sb.ToString();
    }
}
It's ok.  A bit hard to follow however since you're taking steps that really aren't necessary.


It is not necessary to give the StringBuilder a starting capacity.  Just let it do its business and you do yours, it will just work.

However if you really wanted to do this, then that's not a problem.  You can clean it up a bit.  Rather than aggregating over the items when adding up all the lengths, just use Sum() instead.

var totalNamesLength = items.Sum(s =&gt; s.Length);

Don't really have much of a comment on the rest of your code.  I'd be careful of using ==/!= comparisons in a loop that goes over consecutive values, if the loop variable were to ever change in the body of the loop, you'll have a hell of a time trying to debug any problems you have with that.  I'd stick to using &lt; (or appropriate operator) there exclusively.

for (int idx = 1; idx &lt; loopCount; ++idx)
    // ...





I'd write this differently however as this is much more readable to me and compact.

internal static string GetEnumerated(this string[] items)
{
    if (items == null)
        return "";

    if (items.Length &lt;= 1)
        // concatenates all the (0 or 1) items into a single string
        return String.Concat(items);

    // place all but the last in a comma-separated string
    var commaSeparated = String.Join(", ", items.Take(items.Length - 1));
    // include the last item
    return commaSeparated + ", and " + items.Last();
}


Since we know we are dealing with arrays, you won't be paying for much in terms of performance in the LINQ calls.  If that bothers you, it is simple to write the equivalent without using LINQ.

internal static string GetEnumerated(this string[] items)
{
    // I'd leave these in separate conditions
    // to make it clear they are separate cases
    if (items == null)
        return "";
    if (items.Length &lt;= 1)
        return String.Concat(items);

    var commaSeparated = String.Join(", ", items, 0, items.Length - 1);
    return commaSeparated + ", and " + items[items.Length - 1];
}