I often face a situation where I want to “join” a string together using some separator, but have an enumeration of complex items.
Say for example that I have an array of Contacts, each consisting of a firstname and a lastname, something like this:
Contact[] contacts = new Contact[]
{
new Contact() { FirstName="Anders", LastName="Andersson" },
new Contact() { FirstName="Bengt", LastName="Bengtsson" },
new Contact() { FirstName="Cedric", LastName="Cedricsson" }
};
Now say that you want to join together a string with each contacts FirstName separated by commas.
Traditionally, such code could look something like this:
StringBuilder sb = new StringBuilder();
bool first=true;
foreach(Contact c in contacts)
{
if(!first)
sb.Append(",");
sb.Append(c.FirstName);
first = false;
}
string firstNames = sb.ToString();
Ok, it works, but it’s not very elegant. Besides, it would have to be done explicitly for every such complex type we encounter. Bummer.
However, using an Extension method together with the handy Func<T, TResult> predicate, we can write the code in a more generic way:
public static class IEnumerableTExtensions
{
public static string StringJoin<T>(this IEnumerable<T> items,
string separator,
Func<T, string> func)
{
StringBuilder sb = new StringBuilder();
bool first=true;
foreach(T item in items)
{
if(!first)
sb.Append(separator);
sb.Append(func(item));
first = false;
}
return sb.ToString();
}
}
And finally, using this Extension method, we can now write code like this:
string firstNames = contacts.StringJoin(",", c => c.FirstName);
And, the really sweet thing is that this construct is now available for *all* IEnumerable<T>, for example PageDataCollection:
string pageNames = GetChildren(CurrentPage.PageLink).StringJoin(",", p => p.PageName);
/johan