3

In the below code, is it more efficient (in terms of memory and time) to create a List<string> directly, rather than creating a string[] and calling ToList() on it before passing it to SomeMethod()?

If you create the string[] and call ToList(), would it create a List<string> object, as well as already having the string[]?

The reason I ask is that I have seen code where they are creating a string[] and calling ToList() before passing it as an argument to a method with a List<string> parameter, and I wasn't sure if there was any particular reason for that.

class Program
    {
        static void Main(string[] args)
        {            
            var array = new string[] { "str1", "str2" };
            SomeMethod(array.ToList());
            var list = new List<string> { "str1", "str2" };
            SomeMethod(list);                        
        }

        static void SomeMethod(List<string> list)
        {
            //do stuff
        }
    }
David Klempfner
  • 8,700
  • 20
  • 73
  • 153
  • 2
    Are you talking time efficient or memory efficient? – Dodo Aug 26 '15 at 04:08
  • I'm interested in both time and memory efficiency. – David Klempfner Aug 26 '15 at 04:09
  • surely creating a string[] and calling ToList() would lose in terms of both time and memory efficiency? I can't work out why this code was being used in production. It was written by an experienced developer. – David Klempfner Aug 26 '15 at 04:10
  • Even the most experienced of developers have their off days :) – Eraph Aug 26 '15 at 04:11
  • There are methods that modify arguments even if not supposed to... Maybe that person just works in codebase where method names consistently lie about what they do (like `CountItemsInList(list)` may actually remove half of the items... :) ) – Alexei Levenkov Aug 26 '15 at 04:14
  • At least we can be sure that `SomeMethod` is actually a method... I think. Anyway, IEnumerable is, as Backs suggests, a versatile option. – Dodo Aug 26 '15 at 04:17
  • One possible reason - arrays have all kinds of compiler support, so constucting array first and calling `.ToList` (that probably optimized for array version too) *may* be faster than multiple calls to `list.Add(item1),...` which what list initialization is translated too. (Probably would not use it as real reason in my code) – Alexei Levenkov Aug 26 '15 at 04:19
  • It could vary by compiler. Just run some tests and find what works for you. Even if the `ToList` method is slightly faster, convenience and clarity might make you choose otherwise. – Dodo Aug 26 '15 at 04:22

2 Answers2

10
  1. Every .ToList() and .ToArray() creates new objects, allocates memory, copies values. So, try to minimize such operations
  2. Use more common types: IEnumerable, ICollection. Because both list and array are suitable for IEnumerable, for example:

class Program
{
    static void Main(string[] args)
    {            
        var array = new string[] { "str1", "str2" };
        SomeMethod(array);
        var list = new List<string> { "str1", "str2" };
        SomeMethod(list);                        
    }

    static void SomeMethod(IEnumerable<string> list)
    {
        //do stuff
    }
}

Reference.

ToArray Method of List:

public T[] ToArray()
{
  T[] objArray = new T[this._size];
  Array.Copy((Array) this._items, 0, (Array) objArray, 0, this._size);
  return objArray;
}

You can see, it copies data.

ToList method:

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
  if (source == null)
    throw Error.ArgumentNull("source");
  return new List<TSource>(source);
}

You can see, it creates new list object. And constructor List(IEnumerable<T> collection) copies data.

Backs
  • 24,430
  • 5
  • 58
  • 85
0

I'd expect it to be more memory efficient to go straight to the List, but time would depend on inner workings. ToList would probably consist of creating a list and then moving the data over from the array, however, which seems inefficient in terms of time too.

Try running some tests doing each method 100000 or so times, and seeing the amount of time this takes in each test.

Dodo
  • 323
  • 1
  • 8