我正在尝试遍历数据表并从特定列中获取值。到目前为止,我只有 for 循环的骨架。
foreach (var row in currentTable.Rows)
{
var valueAtCurrentRow = row[0];
}
这不符合我的预期。尝试执行row[0]
时出现编译器错误,并显示消息:"无法将 [] 索引应用于 Object 类型的表达式"。但是row
不应该是一个对象,它是一个DataRow
.
为了解决这个问题,我将foreach循环更改为以下内容:
foreach (DataRow row in currentTable.Rows)
{
var valueAtCurrentRow = row[0];
}
为什么有必要这样做?为什么 C# 不能像我尝试迭代string[]
那样推断row
的类型?
为什么 C# 不能像我尝试迭代字符串 [] 时那样推断行的类型?
TL;DR:DataTable
早于泛型:(
DataTable.Rows
被声明返回DataRowCollection
,它派生自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];
}
DataTable
的Rows
属性是DataRowCollection
类型的对象。
DataRowCollection
本身继承自实现ICollection
和IEnumerable
的InternalDataCollectionBase
。
这些集合中包含的数据类型没有比Object
进一步指定,因此无法推断出DataRow
类。
请参阅此处以供参考。
它的原因是行是DataRowCollection
它IEnumerable
而不是IEnumerable<T>
,其中T是DataRow。