Geeks With Blogs
Path Notes of a Kodefu Master blog

Have you ever noticed the goofy logic that must be used to do simple things like creating a comma-delimited string?

public string CommaDelimit(ICollection<string> strings)
{
    StringBuilder sb = new StringBuilder();
    bool first = true;
    foreach (string s in strings)
    {
        if (first)
            first = false;
        else
            sb.Append(',');

        sb.Append(s);
    }
    return sb.ToString();
}

This method should be hidden away in a static method, and in fact this kind of logic is hidden away in a static method. String.Join() will create a properly delimited string for you. However, it only works with a string array, but as in the example above, oftentimes we’re receiving another type of enumerable.

Luckily, LINQ comes with an extension method to convert IEnumerable<T> to T[]: ToArray().

Let me repeat that since the markup makes it difficult to read. LINQ comes with an extension method to convert a generic IEnumerable of a type to an array of that type: ToArray().

public string CommaDelimit(ICollection<string> strings)
{
    return String.Join(",", strings.ToArray());
}

It’s amazing how much ToArray() can simplify a method. In fact, it’s so simple, I would argue that the method to convert the collection to a comma-delimited string is no longer necessary.

Of course, there are more complex situations. How do you handle a collection of non-primitive objects?

public string Names(ICollection<Customer> customers)
{
    StringBuilder sb = new StringBuilder();
    bool first = true;
    foreach (Customer customer in customers)
    {
        if (first)
            first = false;
        else
            sb.Append(',');

        sb.Append(String.Format("{0} {1}", 
            customer.FirstName, customer.LastName));
    }
    return sb.ToString();
}

In this example, the method takes in an ICollection of Customer and returns a comma-delimited list of names. A simple ToArray() is not enough. We must retrieve the data from the object and format it prior to making it comma-delimited.

public string Names(ICollection<Customer> customers)
{
    var names = from c in customers
                select String.Format("{0} {1}",
                c.FirstName, c.LastName);

    return String.Join(",", names.ToArray());
}

A simple LINQ statement does the trick! Of course, this being C#, there is an alternate way of writing this code.

public string Names(ICollection<Customer> customers)
{
    return String.Join(",", 
        customers.Select(c => String.Format("{0} {1}", 
            c.FirstName, c.LastName)).ToArray());
}

I prefer the LINQ syntax to the lambda expression in this situation due to improved readability. However, both simplify the statements required to create a comma-delimited string based on data from a list of objects. Keep this in your arsenal for the next time you’re confronted with refactoring goofy logic from the 2.0 days of C#.

Note: Cross posted from KodefuGuru.
Permalink
Posted on Monday, July 6, 2009 6:09 PM | Back to top


Comments on this post: Refactor ForEach to Join

# re: Refactor ForEach to Join
Requesting Gravatar...
Hey, that was interesting,

It was a good post those like me who are new to linq

Thanks for bringing this up
Left by web development company on Aug 11, 2009 12:59 PM

Your comment:
 (will show your gravatar)


Copyright © Chris Eargle | Powered by: GeeksWithBlogs.net