Separator Delimited ToString for Array, List, Dictionary, Generic IEnumerable

By admin - Last updated: Sunday, September 21, 2008 - Save & Share - 13 Comments

Often programmers want to convert an array into one string with for example comma delimited.
Traditionally, in C#, it can be achieved by

int[] array = {1,2,3};
string delimited = string.Join(",", array);
Console.WriteLine(delimited ) // output: "1,2,3"
 

However, string.Join does not apply to any generic IEnumerable object. It would be so much easier if this method behavior could be applied to all IEnumerable types.
For example,

int[] intArray = { 1, 2, 3 };
Console.WriteLine(intArray.ToString(","));
// output 1,2,3
List list = new List{"a","b","c"};
Console.WriteLine(list.ToString("|"));
// output a|b|c
 

In DOT NET 3+, we can utilize extension method to extend ToString method for any generic IEnumerable objects.

Here is the extension method which can make this work. All it does is to perform some basic checks so that the arguments passed in are sensible, then it uses LINQ constructs an array of string by calling ToString on each element (instance of T) of the generic IEnumerable object. Then It joins each string by the seperator passed in.

public static class ExtensionMethods
{
    // for generic interface IEnumerable<T>
    public static string ToString<T>(this IEnumerable<T> source, string separator)
    {
        if (source == null)
            throw new ArgumentException("Parameter source can not be null.");

        if (string.IsNullOrEmpty(separator))
            throw new ArgumentException("Parameter separator can not be null or empty.");

        string[] array = source.Where(n => n != null).Select(n => n.ToString()).ToArray();

        return string.Join(separator, array);
    }

    // for interface IEnumerable
    public static string ToString(this IEnumerable source, string separator)
    {
        if (source == null)
            throw new ArgumentException("Parameter source can not be null.");

        if (string.IsNullOrEmpty(separator))
            throw new ArgumentException("Parameter separator can not be null or empty.");

        string[] array = source.Cast<object>().Where(n => n != null).Select(n => n.ToString()).ToArray();

        return string.Join(separator, array);
    }
}

As long as the code references this ExtensionMethod sclass, the intelliSense would pop up the extended ToString(string seperator) method, see the picture below,

tostring extension method

tostring extension method

Here is the complete working copy of the code which performs various generic IEnumerable delimited ToString operations including T as a complex type.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace ToString
{
    class Program
    {
        static void Main(string[] args)
        {
            // Array ToString "," separated
            int[] intArray = { 1, 2, 3 };
            Console.WriteLine(intArray.ToString(","));
            // output: 1,2,3

            // ArrayList ToString ":" separated
            ArrayList arrayList = new ArrayList() { 1, 2, 3 };
            Console.WriteLine(arrayList.ToString(":"));
            // output 1:2:3

            // A class object List ToString " - " separated
            List<Foo> foos = new List<Foo>()
            {
                new Foo() { Name = "foo1", Number = 1 },
                new Foo() { Name = "foo2", Number = 2 },
                new Foo() { Name = "foo3", Number = 3 },
            };
            Console.WriteLine(foos.ToString(" - "));
            // output 'foo1 1' - 'foo2 2' - 'foo3 3'

            // A struct List ToString "||" separated
            List<StructFoo> sfoos = new List< StructFoo >()
            {
                new StructFoo() { Name = "sfoo1", Number = 1 },
                new StructFoo() { Name = "sfoo2", Number = 2 },
                new StructFoo() { Name = "sfoo3", Number = 3 },
            };
            Console.WriteLine(sfoos.ToString("||"));
            // output 'sfoo1 1'||'sfoo2 2'||'sfoo3 3'

            // A generic dictionary ToString "," separated
            Dictionary< int, Foo > dictionary = new Dictionary< int, Foo >()
            {
              { 1, new Foo() { Name = "foo1", Number = 1 }},
              { 2, new Foo() { Name = "foo2", Number = 2 }},
              { 3, new Foo() { Name = "foo3", Number = 3 }},
            };
            Console.WriteLine(dictionary.ToString(","));
            // output: [1, 'foo1 1'],[2, 'foo2 2'],[3, 'foo3 3']

            // string as IEnumerable char
            string text = "abcdefg";
            Console.WriteLine(text.ToString(","));
            // output: a,b,c,d,e,f,g

            Console.ReadLine();
        }

        class Foo
        {
            public string Name { get; set; }
            public int Number { get; set; }
            public override string ToString()
            {
                return "'" + Name + " " + Number + "'";
            }
        }

        struct StructFoo
        {
            public string Name { get; set; }
            public int Number { get; set; }
            public override string ToString()
            {
                return "'" + Name + " " + Number + "'";
            }
        }
    }
}

It would be interesting to have the similar functionalities builtin to the framework, it saves programmers a lot of time during development.

Please let me know where the code can be enhanced and bug fix etc.

Download the Source Code in this example

UPDATE @30-Sept-2009
kissedsmiley pointed out the intArray typo (it should be arrayList)
and after clear the typo, it wouldn’t work because arrayList implements IEnumerable not the generic IEnumerable, therefore I’ve also added the ToString extension method for IEnumerable.




Posted in LINQ • Tags: , , , , Top Of Page

13 Responses to “Separator Delimited ToString for Array, List, Dictionary, Generic IEnumerable”

Comment from Anonymous
Time October 29, 2008 at 10:21 pm

Very useful, just what I was looking for actually. I had to add the tag to make it work though:

public static string ToString(this IEnumerable source, string separator) { }

Comment from admin
Time November 3, 2008 at 6:37 pm

Sometimes, the code highlighter remove tags, thanks for pointing this out, I have fixed it.

Comment from kk
Time April 28, 2009 at 7:53 am

Thanks. This was really useful. Helped me save time. However your page does not show up on a google/live search?

Comment from Anonymous
Time June 9, 2009 at 8:49 am

Hi,
I was trying this code but I keep getting this error:
“No overload for method takes 1 argument.” on all the Console.WriteLine as in this case.
Console.WriteLine(intArray.ToString(“,”));

Also I did not understand what do you mean by fixing the tag :
public static string ToString(this IEnumerable source, string separator) { }

Please elaborate.
Zullu

Comment from admin
Time June 10, 2009 at 10:07 pm

Hi Zullu,
You can download the solution file by clicking the link at bottom of this post. or http://www.codemeit.com/wp-content/uploads/2008/09/tostringextensionmethod.zip

Comment from Thorsten
Time July 4, 2009 at 4:07 am

Maybe there is a way to make this work with my Generic ToString() method? So far it fails returning the contents of a list correctly, therefore I have to copy it to an array.
As far as I understand though, essentially you are also copying to an array first. Do you think there are any other solutions, since this could become a performance issue for large lists.
Maybe you can have a look and just leave a comment, to let me know what you think?

Here the link to the blog I mentioned in the previous comment: Here it is

Comment from admin
Time July 5, 2009 at 1:03 am

Hi Thorsten,

I had a look at your generic ToString by using reflection, that is good.
But reflection is quite expensive operation. I don’t think it fits the collection, enumerable scenario.
string.Join for array is optimized by .net, it is very fast operation.

Comment from kissedsmiley
Time September 30, 2009 at 4:46 am

thank you for this nice post. note that due to a typo, the ArrayList test is not performed:

ArrayList arrayList = new ArrayList() { 1, 2, 3 };
Console.WriteLine(intArray.ToString(“:”));

If one changes the ‘intArray’ to ‘arrayList’, it will fail because ArrayList has no ToString method! So the only way I know of to get around it is by writing a wrapper class or building a custom, local handler, either of which is ugly.

Comment from admin
Time September 30, 2009 at 2:12 pm

@kissedsmiley
Thanks for point out the point. But one correction in your comment. ArrayList wouldn’t have the ToString extension method applied because it implements IEnumerable(not generic IEnumerable). Therefore, I’ve added

public static string ToString(this IEnumerable source, string separator)
{…}

so

Console.WriteLine(arrayList .ToString(”:”));

will work for you now.

Comment from Augustandre
Time October 28, 2009 at 5:47 am

Thanks.

Comment from IndyCoder
Time December 24, 2009 at 10:55 am

Thank you! Solved a particular annoying issue I had to deal with. List being passed as a comma separated list to a stored procedure (which then parsed it into a single column table of uniqueidentifier).
I was looking around for ways to deal with this and had found one that was a method that had a string builder in it…but I like yours a lot better. Worked perfect for me when I just copy/pasted the code here on the page. Just had to add a Using System.Collection; to cover the second method. After that, a using that referenced the module I put this in, and I was good to go. THANKS!

Comment from Zohar
Time January 22, 2010 at 10:54 pm

Can I just say few warm words ;) It’s so nice here, good atmosphere, well done :) !.
I am from Sudan and too poorly know English, give please true I wrote the following sentence: “Files are also alternative to stick criminal states of their second, free from any court or available psychologist that may be argued by the restrictions of their killing, criminal justice.”

THX 8), Zohar.

Comment from Avi
Time March 8, 2010 at 12:25 pm

Using the generic type “System.Collections.Generic.IEnumerable requires ’1′ type arguments

I think it’s something to do with using of System.Collection vs. System.Collections.Generic for IEnumerable.

Write a comment


Captcha: three − = 1