Josema Josema - 8 months ago 60
C# Question

Convert generic List/Enumerable to DataTable?

I have few methods that returns different Generic Lists.

Exists in .net any class static method or whatever to convert any list into a datatable? The only thing that i can imagine is use Reflection to do this.

IF i have this:

List<Whatever> whatever = new List<Whatever>();

(This next code doesn't work of course, but i would like to have the possibility of:

DataTable dt = (DataTable) whatever;

Answer Source

Here's a nice 2013 update using FastMember from NuGet:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data)) {

This uses the FastMember's meta-programming API for maximum performance. If you want to restrict it to particular members (or enforce the order), then you can do that too:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) {

Editor's Dis/claimer: FastMember is a Marc Gravell project. Its gold and full-on flys!

Yes, this is pretty much the exact opposite of this one; reflection would suffice - or if you need quicker, HyperDescriptor in 2.0, or maybe Expression in 3.5. Actually, HyperDescriptor should be more than adequate.

For example:

// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ToDataTable<T>(this IList<T> data)
    PropertyDescriptorCollection props =
    DataTable table = new DataTable();
    for(int i = 0 ; i < props.Count ; i++)
        PropertyDescriptor prop = props[i];
        table.Columns.Add(prop.Name, prop.PropertyType);
    object[] values = new object[props.Count];
    foreach (T item in data)
        for (int i = 0; i < values.Length; i++)
            values[i] = props[i].GetValue(item);
    return table;        

Now with one line you can make this many many times faster than reflection (by enabling HyperDescriptor for the object-type T).

edit re performance query; here's a test rig with results:

Vanilla 27179
Hyper   6997

I suspect that the bottleneck has shifted from member-access to DataTable performance... I doubt you'll improve much on that...


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
public class MyData
    public int A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public decimal D { get; set; }
    public string E { get; set; }
    public int F { get; set; }

static class Program
    static void RunTest(List<MyData> data, string caption)
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
        Stopwatch watch = Stopwatch.StartNew();
        for (int i = 0; i < 500; i++)
        Console.WriteLine(caption + "\t" + watch.ElapsedMilliseconds);
    static void Main()
        List<MyData> foos = new List<MyData>();
        for (int i = 0 ; i < 5000 ; i++ ){
            foos.Add(new MyData
            { // just gibberish...
                A = i,
                B = i.ToString(),
                C = DateTime.Now.AddSeconds(i),
                D = i,
                E = "hello",
                F = i * 2
        RunTest(foos, "Vanilla");
        RunTest(foos, "Hyper");
        Console.ReadLine(); // return to exit