C# allows and provides us with some methods to populate an array with the same value. In this article, we are going to explore these built-in techniques and write our own approach. At the end of this article, we are going to test, with a performance benchmark, all these approaches to check which is the fastest one.Â
There are a lot of topics to cover in this article, so let’s start preparing our environment.
Preparing the Environment
Initially, let’s create a class that is going to represent the elements of our array:
public class Article { public string? Title { get; set; } public DateTime LastUpdate { get; set; } public override string ToString() { return $" Title: {Title} | Last update: {LastUpdate}"; } }
Next, we should create a method to return a new instance of the article’s array and set its size to 10 elements:
public static Article[] InstantiateInitialArray() { return new Article[10]; }
Once we have our class and our array ready, let’s start populating it.
Populate an Array With Array.Fill
Since .NET Core 2.0 and .NET Standard 2.1, we can use the Array.Fill()
method to achieve this result:
Array.Fill(array, value);
The first parameter represents the array we want to fill, and the second represents the value we want to assign to each index of this array. This is a generic and static method, which means we can use this method with arrays of any object type, and we don’t need to instantiate the Array
class to use it.Â
Besides those two parameters, it is worth mentioning that the Fill
method provides an overload where we can pass a start index and a count variable, both integers. When we call this method passing these two additional parameters, the result is going to be a little different:
Array.Fill(array, value, 5, 2);
Here, once we send 5 as the start index and 2 as the count, our array is going to keep all the previous values, except for indexes 5 and 6. These indexes are going to receive the new value that is represented as our second parameter.Â
Using Enumerable.Repeat to Populate an Array in C#
Under the System.Linq
namespace, we have Enumerable.Repeat
. Let’s check how to use it:
var articles = Enumerable.Repeat(value, 10).ToArray();
Similar to the method above, this is a static and generic method, however, it doesn’t receive an array as a parameter, but the value we want to repeat and an integer to represent the number of times we want to repeat (count
).
It requires that our last parameter (count
) is greater than zero, otherwise, it throws an ArgumentOutOfRangeException
.
This method returns an instance of the Enumerable
class. Once we want our result as an array, we should cast it using ToArray()
.
Similar to the Array.Fill()
approach, this technique gives us a shallow copy of the elements. It means that, when we change any property’s value of the element we used to fill this array, this change is going to propagate through the entire array. That happens because .NET is not creating a new element for each index, but, referencing the same element every time.
Using Iteration Statement to Populate an Array in C#
Let’s create a new ForStatement
method to see how we can populate an array using simple iteration:
public Article[] ForStatement(Article[] articles, Article article) { for (int index = 0; index < articles.Length; index++) { articles[index] = new Article { Title = article.Title, LastUpdate = article.LastUpdate }; } return articles; }
Our method returns an array of articles and receives two input parameters. The first represents an empty array that we want to fill and the second parameter is the element we are going to use to fill our array.
First, we start a loop iterating through the entire array (articles.Length
). Then, within every iteration, we assign a new Article
instance to each index of the array.
Note that for each iteration, we are instantiating a new article. Otherwise, if we just assign the article we receive as a parameter, every index of our array will reference the same element. This means once we change the Title
or the LastUpdate
from one object in the array, all indexes are going to receive this change.
Instantiating and Populating a Very Small Array
Once we are not lazy and we have a very small array, there’s an easier form to achieve the same results we previously studied:
public Article[] InstantiateArrayManually() { return new Article[] { new Article { Title = "How to Copy Array Elements to New Array in C#", LastUpdate = new DateTime(2022,01,31)}, new Article { Title = "How to Copy Array Elements to New Array in C#", LastUpdate = new DateTime(2022,01,31)} }; }
Here, we create a new method that returns our array of articles filled with the elements.
Benchmark
Let’s implement a performance benchmark to show the difference between the above approaches.
First, we are going to create an array with 100 thousand elements and an object that will fill all these positions:
private Article[] _benchMarkArray = new Article[1000 * 100]; private Article _benchmarkArticle = new() { Title = "How to Copy Array Elements to New Array in C#", LastUpdate = new DateTime(2022, 01, 31) };
To make it easier to read, inside brackets, instead of writing 100000, we use 1000*100.
After running our benchmark, we can inspect the result:
| Method | Mean | Error | StdDev | |----------------- |-----------:|----------:|----------:| | FillArray | 263.1 us | 5.40 us | 15.84 us | | EnumerableRepeat | 765.1 us | 20.40 us | 60.16 us | | ForStatement | 3,525.3 us | 113.47 us | 334.58 us |
The fastest technique is Array.Fill()
. It is almost 3 times faster than Enumerable.Repeat
and more than 13 times faster than when we use iteration loop.
On the other hand, the ForStatement
method is the only one that does a deep copy of elements.
Once our ForStatement
showed us results far worse than any other techniques, we are going to create a new method and try the same for statement, this time, using a shallow copy. Let’s create this new method:
public Article[] ForStatementShallowCopy(Article[] articles, Article article) { for (int index = 0; index < articles.Length; index++) { articles[index] = article; } return articles; }
Results after running the benchmark for the second time:
| Method | Mean | Error | StdDev | |------------------------ |-----------:|---------:|---------:| | FillArray | 260.6 us | 5.77 us | 9.37 us | | EnumerableRepeat | 776.2 us | 20.09 us | 9.44 us | | ForStatement | 3,640.2 us | 54.03 us | 73.96 us | | ForStatementShallowCopy | 382.8 us | 7.57 us | 9.29 us |
Note that, the ForStatementShallowCopy
is much faster compared with the ForStatement
method.
Conclusion
In this article, we’ve seen four different approaches to populate arrays and a performance benchmark that helps us to choose the best option depending on our needs. Also, we’ve seen that shallow copy is much faster than deep copy, however, we should understand the problem we want to solve to apply the correct technique.