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 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.

// contains extension methods, it must be a static class. public static class ExtensionMethod {     // apply this extension to any generic IEnumerable object.     public static string ToString<T>(this IEnumerable<T> source,       string separator)     {         if (source == null) throw new ArgumentException("source can not be null.");         if (string.IsNullOrEmpty(separator)) throw new ArgumentException(             "separator can not be null or empty.");         // A LINQ query to call ToString on each elements         // and constructs a string array.         string[] array =          (from s in source           where s != null select s.ToString()           ).ToArray();         // utilise builtin string.Join to concate elements with         // customizable separator.         return string.Join(separator, array);     } }

As long as the code references this ExtensionMethod class, the intelliSense would promot you 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(intArray.ToString(":"));             // output 1:2:3             // A class object List ToString " - " separated             List foos = new List()             {                 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 sfoos = new List()             {                 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 dictionary = new Dictionary()             {               { 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']             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 Source Code in this example

Tags: , , , ,

admin on September 20th, 2008
Pointer usage in C#, it must be in unsafe context
static unsafe void Main() {     int i;     int[] array = { 11, 22, 33 };     // pointer pi has the address of variable i     int* pi = &amp; i;     // ppi(addess of pi) < pi(addess of i) < i(0)     i = 0;     // dereference the pi, i.e. *pi is i     Console.WriteLine("i = {0}", *pi); // output: i = 0     // since *pi is i, equivalent to i++     (*pi)++;     Console.WriteLine("i = {0}", *pi); // output: i = 1     // pointer to a pointer, pointer ppi has the address     // of variable pi     int** ppi = π         // since *ppi is pi, one more dereference  *pi is i         // equivalent to i += 2     * *ppi += 2;     Console.WriteLine("i = {0}", *pi);// output: i = 3     // pointer to an array     fixed (int* parray = array)     {         // get a copy of parray in fixed context.         int* p = parray;         Console.WriteLine(*(p++));// output: 11         Console.WriteLine(*(p++));// output: 22         Console.WriteLine(*(p++));// output: 33     }     Console.ReadLine(); }

Tags: , ,