Creating a CSV stream from an object I have this code that gets a CSV string from a list of objects where the first row in the string is the object's properties and the rows underneath are the properties values. I then create a MemoryStream of the string so it's about the same as reading from an actual .csv file into a Stream. Is there any way to cutdown on this code and perhaps do more with LINQ?
public class Lead
{
    public string FirstName { get; set; }   
    public string MiddleName { get; set; }
    public string LastName { get; set; }
}
...

List&lt;Lead&gt; leads = new List&lt;Lead&gt;();
Lead lead1 = new Lead();
lead1.FirstName = &quot;Joe&quot;;
lead1.MiddleName = &quot;M&quot;;
lead1.LastName = &quot;DiFabio&quot;;
leads.Add(lead1);

Lead lead2 = new Lead();
lead2.FirstName = &quot;Dave&quot;;
lead2.MiddleName = &quot;&quot;;
lead2.LastName = &quot;Palacios&quot;;
leads.Add(lead2);

Lead lead3 = new Lead();
lead3.FirstName = &quot;Andy&quot;;
lead3.MiddleName = &quot;A&quot;;
lead3.LastName = &quot;Nevers&quot;;
leads.Add(lead3);

List&lt;string&gt; headers = typeof(Lead).GetProperties().Select(x =&gt; x.Name).ToList();
string s = string.Join(&quot;,&quot;, headers);

foreach (Lead lead in leads)
{
    List&lt;object&gt; values = typeof(Lead).GetProperties().Select(prop =&gt; prop.GetValue(lead)).ToList();
    string ss = string.Join(&quot;,&quot;, values);
    s = $&quot;{s}\n{ss}\n&quot;;
}

MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(s));
Let's do some performance tweaks.
I will measure the time simply with Stopwatch and first of all I'll cleanup your code to generate proper CSV (without reduntant empty lines as initial).
List&lt;string&gt; headers = typeof(Lead).GetProperties().Select(x =&gt; x.Name).ToList();
string s = string.Join(&quot;,&quot;, headers) + Environment.NewLine;

foreach (Lead lead in leads)
{
    List&lt;object&gt; values = typeof(Lead).GetProperties().Select(prop =&gt; prop.GetValue(lead)).ToList();
    string ss = string.Join(&quot;,&quot;, values);
    s += $&quot;{ss}{Environment.NewLine}&quot;;
}

Environment.NewLine returns \r\n on Windows and \n on Linux.
Output will be
FirstName,MiddleName,LastName
Joe,M,DiFabio
Dave,,Palacios
Andy,A,Nevers

Looks like CSV :)
Then to measure performance I'll imagine that you have very large amount of data e.g. 30000 lines. I'll run the test in a loop of 10000 iterations.
TestOriginal
private static string TestOriginal(List&lt;Lead&gt; leads)
{
    List&lt;string&gt; headers = typeof(Lead).GetProperties().Select(x =&gt; x.Name).ToList();
    string s = string.Join(&quot;,&quot;, headers) + Environment.NewLine;

    for (int i = 0; i &lt; 10000; i++)
        foreach (Lead lead in leads)
        {
            List&lt;object&gt; values = typeof(Lead).GetProperties().Select(prop =&gt; prop.GetValue(lead)).ToList();
            string ss = string.Join(&quot;,&quot;, values);
            s += $&quot;{ss}{Environment.NewLine}&quot;;
        }
    return s;
}

Let's run.
Stopwatch sw = new Stopwatch();
sw.Start();
string s = TestOriginal(leads);
sw.Stop();
Console.WriteLine(&quot;Original: {0}ms&quot;, sw.ElapsedMilliseconds);

Original: 3162ms

Ugh. :)
Almost everyone knows that Reflection is slow. Let's somewhat optimize that.
ReflectionTweak
private static string ReflectionTweak(List&lt;Lead&gt; leads)
{
    PropertyInfo[] properties = typeof(Lead).GetProperties();
    List&lt;string&gt; headers = properties.Select(x =&gt; x.Name).ToList();
    string s = string.Join(&quot;,&quot;, headers) + Environment.NewLine;

    for (int i = 0; i &lt; 10000; i++)
        foreach (Lead lead in leads)
        {
            List&lt;object&gt; values = properties.Select(prop =&gt; prop.GetValue(lead)).ToList();
            string ss = string.Join(&quot;,&quot;, values);
            s += $&quot;{ss}{Environment.NewLine}&quot;;
        }
    return s;
}

Go go go
sw.Restart();
string sr = ReflectionTweak(leads);
sw.Stop();
Console.WriteLine(&quot;Reflection tweak: {0}ms, match: {1}&quot;, sw.ElapsedMilliseconds, s == sr);

Output with matching the string to original one
Reflection tweak: 3040ms, match: True

Better but still slow
One more idea - StringBuilder. Afaik, it's the fastest way to build a string (maybe except some unsafe/unmanaged code).
StringBuilderTweak
private static string StringBuilderTweak(List&lt;Lead&gt; leads)
{
    StringBuilder sb = new StringBuilder();
    PropertyInfo[] properties = typeof(Lead).GetProperties();
    sb.AppendLine(string.Join(&quot;,&quot;, properties.Select(x =&gt; x.Name)));

    for (int i = 0; i &lt; 10000; i++)
        foreach (Lead lead in leads)
        {
            sb.AppendLine(string.Join(&quot;,&quot;, properties.Select(prop =&gt; prop.GetValue(lead))));
        }
    return sb.ToString();
}

Interesting...
sw.Restart();
string sb = StringBuilderTweak(leads);
sw.Stop();
Console.WriteLine(&quot;StringBuilder tweak: {0}ms, match: {1}&quot;, sw.ElapsedMilliseconds, s == sb);

Output
StringBuilder tweak: 24ms, match: True

WOW!!!
By the way, you may write the output directly to MemoryStream with StreamWriter.
StreamWriterTweak
private static MemoryStream StreamWriterTweak(List&lt;Lead&gt; leads)
{
    MemoryStream ms = new MemoryStream();
    // Encoding.UTF8 produces stream with BOM, new UTF8Encoding(false) - without BOM
    using (StreamWriter sw = new StreamWriter(ms, new UTF8Encoding(false), 8192, true)) 
    {
        PropertyInfo[] properties = typeof(Lead).GetProperties();
        sw.WriteLine(string.Join(&quot;,&quot;, properties.Select(x =&gt; x.Name)));

        for (int i = 0; i &lt; 10000; i++)
            foreach (Lead lead in leads)
            {
                sw.WriteLine(string.Join(&quot;,&quot;, properties.Select(prop =&gt; prop.GetValue(lead))));
            }
    }
    ms.Position = 0;
    return ms;
}

Must be fast too...
sw.Restart();
MemoryStream stream = StreamWriterTweak(leads);
sw.Stop();
Console.WriteLine(&quot;StreamWriter tweak: {0}ms, match: {1}&quot;, sw.ElapsedMilliseconds, s == Encoding.UTF8.GetString(stream.ToArray()));

Output
StreamWriter tweak: 28ms, match: True

Yes!

The fastest
StringBuilder sb = new StringBuilder();
PropertyInfo[] properties = typeof(Lead).GetProperties();
sb.AppendLine(string.Join(&quot;,&quot;, properties.Select(x =&gt; x.Name)));

foreach (Lead lead in leads)
{
    sb.AppendLine(string.Join(&quot;,&quot;, properties.Select(prop =&gt; prop.GetValue(lead))));
}
string s = sb.ToString();

The whole code to reproduce and play more
internal class Program
{
    public static void Main(string[] args)
    {
        List&lt;Lead&gt; leads = new List&lt;Lead&gt;();
        Lead lead1 = new Lead();
        lead1.FirstName = &quot;Joe&quot;;
        lead1.MiddleName = &quot;M&quot;;
        lead1.LastName = &quot;DiFabio&quot;;
        leads.Add(lead1);

        Lead lead2 = new Lead();
        lead2.FirstName = &quot;Dave&quot;;
        lead2.MiddleName = &quot;&quot;;
        lead2.LastName = &quot;Palacios&quot;;
        leads.Add(lead2);

        Lead lead3 = new Lead();
        lead3.FirstName = &quot;Andy&quot;;
        lead3.MiddleName = &quot;A&quot;;
        lead3.LastName = &quot;Nevers&quot;;
        leads.Add(lead3);

        Stopwatch sw = new Stopwatch();
        sw.Start();
        string s = TestOriginal(leads);
        sw.Stop();
        Console.WriteLine(&quot;Original: {0}ms&quot;, sw.ElapsedMilliseconds);
        sw.Restart();
        string sr = ReflectionTweak(leads);
        sw.Stop();
        Console.WriteLine(&quot;Reflection tweak: {0}ms, match: {1}&quot;, sw.ElapsedMilliseconds, s == sr);
        sw.Restart();
        string sb = StringBuilderTweak(leads);
        sw.Stop();
        Console.WriteLine(&quot;StringBuilder tweak: {0}ms, match: {1}&quot;, sw.ElapsedMilliseconds, s == sb);

        //MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(s));

        sw.Restart();
        MemoryStream stream = StreamWriterTweak(leads);
        sw.Stop();
        Console.WriteLine(&quot;StreamWriter tweak: {0}ms, match: {1}&quot;, sw.ElapsedMilliseconds, s == Encoding.UTF8.GetString(stream.ToArray()));

        Console.ReadKey();
    }

    private static string TestOriginal(List&lt;Lead&gt; leads)
    {
        List&lt;string&gt; headers = typeof(Lead).GetProperties().Select(x =&gt; x.Name).ToList();
        string s = string.Join(&quot;,&quot;, headers) + Environment.NewLine;

        for (int i = 0; i &lt; 10000; i++)
            foreach (Lead lead in leads)
            {
                List&lt;object&gt; values = typeof(Lead).GetProperties().Select(prop =&gt; prop.GetValue(lead)).ToList();
                string ss = string.Join(&quot;,&quot;, values);
                s += $&quot;{ss}{Environment.NewLine}&quot;;
            }
        return s;
    }

    private static string ReflectionTweak(List&lt;Lead&gt; leads)
    {
        PropertyInfo[] properties = typeof(Lead).GetProperties();
        List&lt;string&gt; headers = properties.Select(x =&gt; x.Name).ToList();
        string s = string.Join(&quot;,&quot;, headers) + Environment.NewLine;

        for (int i = 0; i &lt; 10000; i++)
            foreach (Lead lead in leads)
            {
                List&lt;object&gt; values = properties.Select(prop =&gt; prop.GetValue(lead)).ToList();
                string ss = string.Join(&quot;,&quot;, values);
                s += $&quot;{ss}{Environment.NewLine}&quot;;
            }
        return s;
    }

    private static string StringBuilderTweak(List&lt;Lead&gt; leads)
    {
        StringBuilder sb = new StringBuilder();
        PropertyInfo[] properties = typeof(Lead).GetProperties();
        sb.AppendLine(string.Join(&quot;,&quot;, properties.Select(x =&gt; x.Name)));

        for (int i = 0; i &lt; 10000; i++)
            foreach (Lead lead in leads)
            {
                sb.AppendLine(string.Join(&quot;,&quot;, properties.Select(prop =&gt; prop.GetValue(lead))));
            }
        return sb.ToString();
    }

    private static MemoryStream StreamWriterTweak(List&lt;Lead&gt; leads)
    {
        MemoryStream ms = new MemoryStream();
        // Encoding.UTF8 produces stream with BOM, new UTF8Encoding(false) - without BOM
        using (StreamWriter sw = new StreamWriter(ms, new UTF8Encoding(false), 8192, true))
        {
            PropertyInfo[] properties = typeof(Lead).GetProperties();
            sw.WriteLine(string.Join(&quot;,&quot;, properties.Select(x =&gt; x.Name)));

            for (int i = 0; i &lt; 10000; i++)
                foreach (Lead lead in leads)
                {
                    sw.WriteLine(string.Join(&quot;,&quot;, properties.Select(prop =&gt; prop.GetValue(lead))));
                }
        }
        ms.Position = 0;
        return ms;
    }

    public class Lead
    {
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
    }
}