The Enumerable is using a Random Number Generator
There are several valid reasons in the comments above, but here's another one too: the elements contain a value popped from a random number generator.
TemperatureC = Random.Shared.Next(-20, 55)
.ToArray means that anyone iterating the IEnumerable several times would always get the same values.
Now consider what happens without .ToArray.
The use of .Select in the IEnumerable means that it's deferred execution. If you iterated the IEnumerable twice then you would trigger a different Random operation each time. This would cause several problems.
Confusion when debugging
For anyone who manages to put a breakpoint on the returned IEnumerable and views the value in the Visual Studio debugger, they'd potentially get a different Results set each time they expanded and collapsed the debug output. Even without restarting the program.
As this code is in a Microsoft example where people new to the technology are trying to learn, they're even more likely to misunderstand this implication of deferred execution - and be thoroughly confused.
Action Filters in ASP.NET
This is an ASP.NET example, so it's possible the developers would choose to add Action Filters^1.
Action Filters can let you write code that runs after the controller method has generated the results, and allow you to manipulate it. You might naively (wrongly) write a method that iterates the IEnumerable more than once for performing some post-processing operation. I don't have the exact Action Filter syntax to hand, but consider something like the following:
public class TemperatureSmoothingFilter : IActionFilter
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var temps = context.Result as IEnumerable<WeatherForecast>;
// **Bad code!**
// Find the difference between each adjacent temperature reading.
// Achieve this by Zipping the IEnumerable back with itself.
tempsWithDifferences = temps
.Zip(temps.Skip(1))
.Select((a,b) => new WeatherForecastWithDelta()
{
TemperatureDifferenceC = b.TemperatureC - a.TemperatureC,
TemperatureC = b.TemperatureC,
// etc
});
// We have just iterated the randomised IEnumerable twice
// so the temperature difference values will be nonsense.
// Overwrite result
context.Result = tempsWithDifferences;
}
}
public class WeatherForecastWithDelta : WeatherForecast
{
public int TemperatureDifferenceC { get; set; } = 0
}
NB this is a terrible idea. A filter is not the right place for business logic! But again, when authors are writing example code for developers to experiment with, they should allow for them doing the "wrong" thing by protecting them from side effects.
Summary
Even though it's good programming practice to only iterate an IEnumerable once, it's a common mistake for people to iterate multiple times.
So for an example where the IEnumerable definitely gives different results each time, it's safer to immediately materialise it into an array.
.ToArray()does not provide any advantage in this scenario, it even causes unnecessary memory allocation, but in my opinion, consider it only as a starting template, not a best practice.using ()clause?ToArrayif there is a bug in your code (e.g.Summariesisnull) that you will see that exception clearer where the bug is.