Updated on

In C#, we print an array’s elements by writing them to the console one at a time in a loop, or by joining them into a single string and writing it once with Console.WriteLine(string.Join(", ", array)). Passing the array itself to Console.WriteLine() prints its type name instead.

We are going to look at six ways to do it, and then compare them to check which are the fastest and the slowest ones.

To download the source code for this article, you can visit our GitHub repository.

Let’s start.

Preparing the Environment

Let’s create an array we want to print out and fill it with some elements. It goes inside a class, together with the methods below:

private static readonly int[] _array = [1, 4, 6, 7, 9, 3, 5];

It is important to mention that one of our methods uses the System.Linq namespace. Projects with implicit usings enabled, which is the default for new projects, already import it. If our project turns implicit usings off, we add the Linq namespace ourselves:

using System.Linq;

Why Does Console.WriteLine Print System.Int32[] Instead of the Elements?

When we pass an array to Console.WriteLine(), the compiler finds no overload that takes an int[], so it picks the one that takes an object. That overload calls the array’s ToString() method and writes whatever comes back.

Arrays don’t override ToString(). They inherit it from System.Object, and that version returns the full name of the type, not the values inside. For an int[] the name is System.Int32[], and a string[] prints System.String[].

So the line compiles and runs without an error, and prints no values at all.

The one exception is a char[]. Console.WriteLine() has an overload just for it, so a character array prints as text.

For every other array, we have to hand the console the elements, not the array. The six methods below either write the elements one at a time, or join them into one string first and write that string once.

The Object.ToString() reference on Microsoft Learn says: “Default implementations of the Object.ToString method return the fully qualified name of the object’s type.” Our article on the ToString method in C# shows how our own types override it.

Using For and Foreach Loops to Print the Elements of an Array

Let’s create a ForLoop method to print out our elements:

public void ForLoop(int[] array)
{
    for (int i = 0; i < array.Length; i++)
    {
        Console.Write($" ==> {array[i]}");
    }
}

As an input parameter, this method receives an array of int. We iterate through this entire array, and for each index, we print the respective element at the console.

We can achieve the same result using the foreach loop:

public void ForeachLoop(int[] array)
{
    foreach (var item in array)
    {
        Console.Write($" ==> {item}");
    }
}

Both loops print the same thing. If we are curious how they differ under the hood, we compare them in our article on for and foreach loops in C#.

Using ForEach Method to Print the Elements of an Array

Let’s see how to print every element of the array using this technique:

public void ToListForEach(int[] array)
{   
    array.ToList().ForEach(element => Console.Write($" ==> {element}"));
}

We receive an array as a parameter. Then, we create a new list using ToList() method. After that, we use the built-in ForEach method, under the List class, to iterate over the array’s elements. We pass to the ForEach method a lambda expression (element => Console.Write($" ==> {element}")) as a parameter. This lambda expression is the Action<int> delegate responsible to print each element. Mind you, ToList() copies the whole array into a new list before ForEach runs, so this approach pays for a copy the others don’t need.

List<T>.ForEach() and the foreach statement look alike, and we explain where they differ in comparing the ForEach method and the foreach statement.

Using String.Join to Print Out Array’s Elements

Another way to print array elements is using string.Join:

Console.Write($" ==> { string.Join(" ==> ", _array)}");

We use the Console.Write method to print all the elements. However, we have to provide those elements. This is where the Join method comes into play. Its responsibility is to concatenate every element of the array (the second parameter) separating each with the string separator (first parameter).

For the everyday case, a comma-separated line on the console, the whole thing fits on one line:

Console.WriteLine(string.Join(", ", _array));

string.Join() has more overloads than we need here, and our article on creating a comma-separated string walks through them.

Print Out Elements Using the Array Class

The Array class provides us with a static method (ForEach) to iterate through an array performing a specific operation. Let’s implement it:

Action<int> print = (element) => Console.Write($" ==> {element}");
Array.ForEach(_array, print);

First, we create an Action Delegate responsible to print the elements on the screen. This Action receives, as a parameter, the element we want to print out.

Secondly, we use the Array class to call the ForEach method. We pass the array we want to iterate through as a parameter and the Action we defined.

It is good to mention that, if any of the parameters we send is null, the ForEach method will throw an ArgumentNullException. 

Print Out Elements Using Span

Let’s create an AsSpan method to print out the elements:

public void AsSpan(int[] array)
{
    var span = array.AsSpan();

    foreach (var item in span)
    {
        Console.Write($" ==> {item}");
    }
}

Here, we create a Span<int> over the input array. A span is a struct that points at the array’s memory, so nothing is copied. After that, we perform an iteration using a foreach loop printing each element on the screen.

This AsSpan method is an extension method in the MemoryExtensions class, in the System namespace. If spans are new to us, our article on the differences between Span and Memory in C# is a good next stop.

Which Way of Printing an Array Is the Fastest?

string.Join() is the fastest of the six by a wide margin. It builds one string out of all the elements and calls Console.Write() once. Every other approach calls Console.Write() once per element.

That difference matters because the console writer flushes after every call. Each call hands its text to the output stream right away instead of collecting it, so a million elements means a million trips to the stream.

How we visit the elements barely counts next to that. A for loop, a foreach loop, a span, List<T>.ForEach() and Array.ForEach() all repeat the same expensive step for each element, which is why their results sit close together and can swap places between runs.

The price of string.Join() is memory. The whole output has to exist as one string before anything reaches the console, so for a very large array, writing in chunks is a reasonable middle ground.

In a separate benchmark class, let’s create a FillElements method responsible to populate an array with one million elements:

private static readonly int[] _array = FillElements(1_000_000);

private static int[] FillElements(int length)
{
    var array = new int[length];

    for (int i = 0; i < length; i++)
    {
        array[i] = Random.Shared.Next(0, 1000);
    }

    return array;
}

Now, let’s check the benchmark results:

| Method        | Mean      | Error    | StdDev    |
|-------------- |----------:|---------:|----------:|
| StringJoin    |  25.53 ms | 0.372 ms |  0.348 ms |
| ForeachLoop   | 256.29 ms | 4.710 ms |  5.235 ms |
| ArrayForEach  | 261.15 ms | 4.529 ms |  4.015 ms |
| AsSpan        | 263.01 ms | 5.169 ms |  7.894 ms |
| ForLoop       | 263.26 ms | 5.181 ms |  5.966 ms |
| ToListForeach | 291.93 ms | 5.806 ms | 10.169 ms |

Printing data is a heavy operation. That explains why five of our six methods took more than 0.2 seconds to run.

The fastest approach is when we use the string.Join (25.53 milliseconds, about 10 times faster than the next one). This method calls Console.Write only once, passing all the elements we want to print as a string.

Every other approach has a very similar efficiency, with just 0.036 seconds of difference when we compare the second-best (ForeachLoop) with the slowest (ToListForeach) approach. We should also understand that, if we run this same benchmark many times, the order of these methods may change.

The sample runs the benchmarks in BenchmarkDotNet’s in-process mode. In the default mode, each benchmark runs in a separate process, and the benchmark host keeps every line that process prints. With millions of writes, that output piles up in the host’s memory. For the numbers above, we sent the console output to NUL, which throws it away. The absolute numbers depend on where the output goes, and the gap between one write and a million writes is the part that carries over.

Here are the six ways side by side, so we can pick one without scrolling back:

ApproachThe printing lineConsole.Write callsMean on .NET 10
for loopConsole.Write($" ==> {array[i]}") inside forone per element263.26 ms
foreach loopConsole.Write($" ==> {item}") inside foreachone per element256.29 ms
List<T>.ForEach()array.ToList().ForEach(element => Console.Write(...))one per element, after copying the array to a list291.93 ms
string.Join()Console.Write($" ==> {string.Join(" ==> ", array)}")one25.53 ms
Array.ForEach()Array.ForEach(array, print)one per element261.15 ms
Span<T>foreach over array.AsSpan()one per element263.01 ms

For a quick look at a small array, any of them is fine. When the array is big or the output matters, string.Join() is the one to reach for.

Conclusion

In this article, we have learned different ways to print the elements of an array using C#.

We have inspected a benchmark that showed us that, printing elements on the screen is a heavy operation and we need to be careful about how much data we want to print on the screen.

We have seen that string.Join() is far ahead because it writes only once, while the other five approaches are very similar when we talk about efficiency, so, among those, it is up to us to decide which one to use daily.

If our array has rows and columns, printing it usually takes nested loops, which we cover in how to print a 2D array to the console.

Tested with .NET 10.0.10, BenchmarkDotNet 0.15.8 and MSTest 4.5.1.