Casting in foreach loop

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?

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow