Back to Blog
C#

C# Array to List: Conversion Methods and Performance

c# array to list: Learn how to convert a C# array to a List using ToList() and the List<T> constructor, including performance and memory tradeoffs.

C#ArraysListsLINQPerformance
Illustration of an array being converted to a list in C# with arrows and brackets.

c# array to list requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

You have an array in C# and you need a List<T> to take advantage of dynamic resizing, LINQ methods that are more convenient on lists, or to pass to an API that expects IEnumerable<T>. The conversion is straightforward, but there are two common approaches, and they have subtle differences worth understanding.

The Two Standard Ways to Convert an Array to a List

The most direct way is to use the LINQ extension method ToList(), which is available on any IEnumerable<T>. Since an array implements IEnumerable<T>, you can call it directly:

using System.Linq; int[] numbers = { 1, 2, 3, 4, 5 }; List<int> list = numbers.ToList();

Alternatively, you can pass the array to the List<T> constructor:

List<int> list = new List<int>(numbers);

Both produce a List<int> containing the same elements in the same order. The constructor is part of the List<T> class itself, so it does not require using System.Linq. The ToList() method is an extension method defined in the System.Linq namespace.

How ToList() Works Internally

ToList() is implemented as a simple call to new List<TSource>(source) in the .NET runtime. It creates a new List<T> and copies every element from the source into the list's internal array. This means the time complexity is O(n), where n is the number of elements in the array. The list's initial capacity is set to the array's length, so no extra resizing occurs during the copy.

The List<T> constructor does exactly the same thing when given an IEnumerable<T>. It also copies the elements and sets the initial capacity to the number of elements if the source implements ICollection<T>. Arrays implement ICollection<T>, so the capacity is set precisely.

Performance and Memory Considerations

Both conversion methods allocate a new List<T> object and a new internal array to hold the elements. For value types, each element is copied; for reference types, the references are copied. This is a shallow copy, so the objects themselves are not duplicated.

If you are converting a large array, the allocation can be significant. If the array is already a List<T>, you might be tempted to call ToList() to get a copy, but that would also allocate a new list. If you need a mutable collection and already have an array, converting once is fine. But if you find yourself converting the same array to a list repeatedly inside a loop, consider converting once and reusing the list.

Another point: if you only need to read the data and not modify the collection, you might not need to convert at all. Arrays support LINQ methods like Where, Select, and ToList() can be called on the array directly without storing the result as a list. However, if you need to add or remove elements, a list is necessary.

When to Use ToList() vs new List<T>(array)

In practice, the two approaches are equivalent in terms of performance and behavior. The choice often comes down to style and dependency on LINQ.

Use ToList() when:

  • You are already working with LINQ and want a concise one-liner.
  • The source is an IEnumerable<T> that might not be an array (e.g., a query result).
  • You want to avoid explicitly naming the List<T> type in the conversion.

Use the List<T> constructor when:

  • You want to avoid adding using System.Linq to the file.
  • You are converting a known array and want to be explicit about the target type.
  • You are writing code that must be compatible with older .NET versions where ToList() might not be available (though it has been available since .NET 3.5).

In most modern C# codebases, ToList() is the idiomatic choice because it reads well and integrates with LINQ pipelines.

Converting Multidimensional and Jagged Arrays

The ToList() method works on single-dimensional arrays because they implement IEnumerable<T>. Multidimensional arrays (e.g., int[,]) do not implement IEnumerable<T>; they implement the non-generic IEnumerable interface. As a result, you cannot call ToList() directly on a multidimensional array. You would need to flatten it manually or use a loop.

Jagged arrays, which are arrays of arrays, do implement IEnumerable<T> where T is the inner array type. For example:

int[][] jagged = new int[][] { new int[] { 1, 2 }, new int[] { 3, 4, 5 } }; List<int[]> listOfArrays = jagged.ToList();

This creates a List<int[]> where each element is one of the inner arrays. If you need a flattened List<int>, you would use SelectMany:

List<int> flatList = jagged.SelectMany(inner => inner).ToList();

For a true multidimensional array, you can iterate over its elements and add them to a list:

int[,] matrix = new int[2, 2] { { 1, 2 }, { 3, 4 } }; List<int> flatList = new List<int>(); foreach (int value in matrix) { flatList.Add(value); }

Common Pitfalls When Converting Arrays to Lists

One common mistake is forgetting to include using System.Linq when calling ToList(). The compiler will throw an error because the extension method is not in scope.

Another pitfall is assuming that ToList() creates a deep copy. For reference types, the list contains the same object references as the array. Modifying an object through the list will affect the array as well, because they point to the same instances. This is often the desired behavior, but it can surprise developers who expect a full copy.

Also, note that converting an array to a list and then modifying the list (adding or removing elements) does not affect the original array. The list is independent after the copy. If you need to modify the array itself, you cannot do so through the list.

Finally, be aware that ToList() on a very large array can cause a large allocation. If you are working with huge datasets, consider whether you really need a list or if an array (or a Span<T>) would be more appropriate.

Practical Example: Converting an Array of Strings for Filtering

Suppose you have an array of names and you want to filter out duplicates and then add a new name. The array is fixed-size, so you need a list to perform these operations.

string[] names = { "Alice", "Bob", "Charlie", "Alice" }; // Convert to list List<string> nameList = names.ToList(); // Remove duplicates nameList = nameList.Distinct().ToList(); // Add a new name nameList.Add("Diana"); // Sort the list nameList.Sort(); foreach (string name in nameList) { Console.WriteLine(name); }

This example shows why you might need a list: the Distinct() method returns an IEnumerable<string>, and you call ToList() again to get a mutable list. The original array remains unchanged, and you can now add or remove items freely.

If you only needed to read the names and not modify them, you could work directly with the array and LINQ:

var distinctNames = names.Distinct().OrderBy(n => n);

But as soon as you need to add or remove elements, a list becomes necessary.

c# array to list: Practical Usage and Code Examples | RYUSLOG DEV