This answer aims to extend and improve some mentions of LINQ-based solutions. It is not an example of a "good" way to solve this per se. Just use string.Join
as suggested when it fits your needs.
Context
This answer is prompted by the second part of the question (a generic approach) and some comments expressing a deep affinity for LINQ.
Given that there is no answer matching all these requirements, I propose an implementation that is based on LINQ, running in linear time, works with enumerations of arbitrary length, and supports generic conversions to string for the elements.
So, LINQ or bust? Okay.
static string Serialize<T>(IEnumerable<T> enumerable, char delim, Func<T, string> toString)
{
return enumerable.Aggregate(
new StringBuilder(),
(sb, t) => sb.Append(toString(t)).Append(delim),
sb =>
{
if (sb.Length > 0)
{
sb.Length--;
}
return sb.ToString();
});
}
This implementation is more involved than many alternatives, predominantly because we need to manage the boundary conditions for the delimiter (separator) in our own code.
It should run in linear time, traversing the elements at most twice.
Once for generating all the strings to be appended in the first place, and zero to one time while generating the final result during the final ToString
call. This is because the latter may be able to just return the buffer that happened to be large enough to contain all the appended strings from the get go, or it has to regenerate the full thing (unlikely), or something in between. See e.g. What is the Complexity of the StringBuilder.ToString() on SO for more information.
Final Words
Just use string.Join
as suggested if it fits your needs, adding a Select
when you need to massage the sequence first.
This answer's main intent is to illustrate that it is possible to keep the performance in check using LINQ. The result is (probably) too verbose to recommend, but it exists.