为什么 C# 不能推断数据表行的类型

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

我正在尝试遍历 DataTable 并从特定列中获取值。到目前为止,我只有 for 循环的骨架。

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

这不符合我的预期。我在尝试执行 row[0] 时收到编译器错误消息:"Cannot apply indexing with [] to an expression of type Object"。但是row应该不是一个对象,是一个DataRow

为了解决这个问题,我将 foreach 循环更改为以下内容:

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

为什么这是必要的?为什么 C# 不能推断 row 的类型,就像我尝试迭代 string[] 时那样?

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 早于仿制药 :(

DataTable.Rows is declared to return DataRowCollection, which derives from InternalDataCollectionBase。它实现了非泛型 ICollection 接口,这意味着编译器无法推断 row 的类型,而不仅仅是 object.

这不是 DataTable 特有的 - 任何时候你有只实现 IEnumerable 而不是 IEnumerable<T> 的东西(并且没有更具体的 GetEnumerator 方法供编译器使用),推断的迭代元素类型只是 object。当您在 foreach 循环中为变量指定显式类型时,编译器会自动为您插入一个强制转换。

我会完全按照您的要求保留更改,但另一种方法是使用 Cast LINQ 方法:

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

DataTableRows属性是DataRowCollection类型的对象。

DataRowCollection 本身继承自 InternalDataCollectionBase 实现 ICollectionIEnumerable.

这些集合中包含的数据类型没有比 Object 进一步指定,因此无法推断为 DataRow class.

参考here

原因是 Rows 是 DataRowCollection,即 IEnumerable 而不是 IEnumerable<T>,其中 T 是 DataRow。