I ran into the following code:
foreach (var row in datatable.Rows.Cast<DataRow>())
{
some code here
}
Now, I think casting in a foreach loop is incorrect, since I think it cast each time it loops. But, I could be wrong, maybe the compiler is smart enough?
On a related note: How can I figure something like this out for myself?
Well it calls Cast<DataRow>
once, but that will actually cast each item as it's fetched. So there is a cast on each iteration (at least potentially; Cast
has an optimization when it knows it's not necessary) but there's only a single method call. The iterator returned by Cast
will fetch items (lazily) from the source (datatable.Rows
here) and cast each item as it's requested by the loop.
See my Edulinq post on Cast
for more information.
Although the waters are a bit muddied here due to Cast
being lazy, it's important to remember that the expression to the right of in
is only ever evaluated once. So a loop of the form:
foreach (var item in complicatedExpression)
{
...
}
is equivalent to:
var items = complicatedExpression;
foreach (var item in items)
{
...
}
The compiler will generate code that calls GetEnumerator()
once, and then uses the result of that to iterate over the collection.
For this specific example, an alternative to using Cast
would be to let the compiler put the cast in the loop itself:
foreach (DataRow row in datatable.Rows)
{
some code here
}
The compiler will perform a cast on each item as it fetches it from the iterator, implicitly. It's a bit sneaky because it's not obviously casting.
As for how you can tell what's going on - you could always use ildasm
to look at the IL. That can be very instructive, but somewhat time-consuming.
See more on this question at Stackoverflow