Thursday, January 31, 2013

Converting a generic list to a CSV string


List<int> myValues;
string csv = String.Join(",", myValues.Select(x => x.ToString()).ToArray());

IEnumerable<T> myList;
string csv = String.Join(",", myList.Select(x => x.ToString()).ToArray());

.NET 4.0 was officially released. Now we can just say
IEnumerable<T> sequence;string csv = String.Join(",", sequence);
IEnumerable<string> can be converted into a string array very easily with LINQ (.NET 3.5):
IEnumerable<string> strings = ...;
string[] array = strings.ToArray();

It's easy enough to write the equivalent helper method if you need to:

public static T[] ToArray(IEnumerable<T> source)
{
    return new List<T>(source).ToArray();
}

Then call it like this:

IEnumerable<string> strings = ...;
string[] array = Helpers.ToArray(strings);

You can then call string.Join. Of course, you don't have to use a helper method:

// C# 3 and .NET 3.5 way:
string joined = string.Join(",", strings.ToArray());
// C# 2 and .NET 2.0 way:
string joined = string.Join(",", new List<string>(strings).ToArray());
The latter is a bit of a mouthful though :)

This is likely to be the simplest way to do it, and quite performant as well - there are other questions about exactly what the performance is like, including (but not limited to) this one.


Then you can just call the method on the original list:

string commaSeparated = myList.JoinStrings(", ");


You can create an extension method that you can call on any IEnumerable:

public static string JoinStrings<T>(
    this IEnumerable<T> values, string separator)
{
    var stringValues = values.Select(item =>
        (item == null ? string.Empty : item.ToString()));
    return string.Join(separator, stringValues.ToArray());
}


3.5, i was still able to do this. Its much more simpler and doesnt need lambda.
String.Join(",", myList.ToArray<string>());

Self-referencing many-to-many recursive relationship code first Entity Framework


class Member
{
    public virtual IList<Member> Friends { get; set; }
    [Key]
    public int MemberId { get; set; }
    public string Name{ get; set; }
}


//By convention, Code First will take uni-directional associations as one to many.
//Therefore you need to use fluent API to let Code First
//know that you want to have a many to many self referencing association:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>().HasMany(m => m.Friends).WithMany();
}
//Note: There is a known bug in CTP5 that won't let you customize the join table column
//names in this scenario.