Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 439
Michael Hancock Avatar asked Feb 08 '18 10:02

Michael Hancock


2 Answers

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];
}
like image 116
Jon Skeet Avatar answered Oct 19 '22 23:10

Jon Skeet


The Rows property of the DataTable is an object of type DataRowCollection.

DataRowCollection itself inherits from InternalDataCollectionBase which implements ICollection and IEnumerable.

The data type contained in these collections isn't any further specified than Object thus it can't be inferred to the DataRow class.

See here for reference.

like image 41
Adwaenyth Avatar answered Oct 19 '22 23:10

Adwaenyth