Why can't C# infer the type of a DataTable Row

I am trying to iterate over a DataTable and get the values from a particular column. So far I just have the Skeleton of the for loop.

foreach (var row in currentTable.Rows)
{
   var valueAtCurrentRow = row[0];
}

This does not work as I expected. I get an compiler error when trying to do row[0], with the message: "Cannot apply indexing with [] to an expression of type Object". But row should not be an object, it is a DataRow.

To fix this I changed the foreach loop to the following:

foreach (DataRow row in currentTable.Rows)
{
   var valueAtCurrentRow = row[0];
}

Why is this necessary? Why can't C# infer the type of row as it would if I was trying to iterate over a string[] for example?

Jon Skeet
people
quotationmark

Why can't C# infer the type of row as it would if I was trying to iterate over a string[] for example?

TL;DR: DataTable predates generics :(

DataTable.Rows is declared to return DataRowCollection, which derives from InternalDataCollectionBase. That implements the non-generic ICollection interface, which means that the compiler can't infer the type of row beyond just object.

This isn't specific to DataTable - any time you have something that only implements IEnumerable rather than IEnumerable<T> (and doesn't have a more specific GetEnumerator method for the compiler to use), the inferred iteration element type is just object. When you specify an explicit type for the variable in the foreach loop, the compiler silently inserts a cast for you.

I'd keep the change exactly as you've got it, but an alternative would be to use the Cast LINQ method:

foreach (var row in currentTable.Rows.Cast<DataRow>())
{
   var valueAtCurrentRow = row[0];
}

people

See more on this question at Stackoverflow