If we are trying to initialize a List with capacity and default value, just like how we initialize a vector in C++ with size and default value, say I'm creating a list of Dictionary to build a graph with weight, there are generally two ways of doing that:
1) Using for loop to build the list manually:
var graph= new List<Dictionary<int, int>>();
for (var i = 0; i < n; i++)
{
graph.Add(new Dictionary<int, int>());
}
2) Using Enumberable.Repeat() to initialize the list:
var graph= Enumerable.Repeat(new Dictionary<int, int>(), n).ToList();
Say now we have a list of node-pair(edge) with weight and want to build a graph on top of that, we would write:
foreach (var list in lists) // List = [[0, 1, 100],[1,2,100],[0,2,500]]
{
int a = list[0], b = list[1], weight= list[2];
if (!graph[a].ContainsKey(b))
graph[a].Add(b, weight);
}
While both approach should theoretically work, the result are quite different. When I try to print the graph with following code:
for (var i = 0; i < graph.Count; i++)
{
var node = graph[i];
foreach (var pair in node)
{
Console.WriteLine($"{i} -> {pair.Key} with price {pair.Value}");
}
}
The result from 1) looks like:
// Correct output
0 -> 1 with price 100
0 -> 2 with price 500
1 -> 2 with price 100
But result from 2) looks like:
// Incorrect result
0 -> 1 with price 100
0 -> 2 with price 100
1 -> 1 with price 100
1 -> 2 with price 100
2 -> 1 with price 100
2 -> 2 with price 100
The behavior of Repeat method seems very odd in this case and on the Doc, there is no mention of such behavior.
My take on that behavior is the Repeat method create ONLY ONE value in the memory and point all list entry to the same memory location. In this case there is only one dictionary created in the memory instead of a new dictionary created for each list entry. And all operations on the dictionary actually happens at the same location. But this won't explain the weird output in the second result.
Any thought? Is it a bug in this Enumerable.Repeat() method or I'm doing it wrong? What is the better way to initialize a list with default value?