What do you suppose happens when this piece of code is run? Please take notice that the secondary foreach loop is using the same dataset.
DataSet dsMain = GetMainDataset();
foreach (DataRow dr in dsMain.Tables[0].Rows)
{
Console.WriteLine(dr["ID"] + " | " + dr["NAME"]);
dsMain = GetSecondaryDataset();
foreach (DataRow drSecondary in dsMain.Tables[0].Rows)
Console.WriteLine(drSecondary["DETAIL"]);
}
Will it generate a run time error? Infinite loop? Half the results? Is the DataRow variable dr equal to drSecondary? Is dsMain the same all over the code?
And, of course, WHY?
Well, let's take it step by step.
We first step through the first foreach loop and notice the dsMain pointer is 15335436 - badly shown in the photos in the watch.
The dataset dsMain contains 2 columns: ID and NAME.
We step after the
dsMain = GetSecondaryDataset();
and see that the pointer has changed to 15400908 - the assignment was successful and we have a new dataset.
The dataset dsMain now contains one column called DETAIL.
At this point we can raise the question: what happens after this inner foreach finishes and the loop goes back to the outer one?
Will the outer foreach loop end because the rows of the dataset were run to the end by the inner foreach loop?
Will the outer foreach loop crash because
Console.WriteLine(dr["ID"] + " | " + dr["NAME"]);
is looking for columns ID and NAME that don't exist in dsMain dataset - remember the previous step where dsMain became a new dataset, with only one column DETAIL?
In order to answer our question, we need to look at the disassembly.
Did you catch the idea? The foreach loops are not using direct pointer to the dataset dsMain rows collection, but rather pointers to the enumerator to the rows collection. And the enumerator enumerates through the collection regardless of what happens to the dsMain pointer.
So the answer is: the code will work fine, because foreach loops use the (pointers to the) enumerators of the rows collection, not pointers to the rows.
More...