为什么编译器无法确定 .Rows 返回 DataRows 的集合?
因为 DataTable Rows (DataRowCollection) 与枚举一起工作的方式,也部分与foreach
工作方式有关,以及这一切有多古老。
首先介绍一下foreach
:
foreach
不是真的东西;它更像是 while 循环的语言快捷方式,它获取对象上的枚举器并重复调用MoveNext
, MoveNext
, MoveNext
... 直到MoveNext
返回 false,此时它停止循环。while 循环体所做的第一件事是调用Current
枚举器,并将响应加载到您在foreach
声明中指定的变量中。您编写的循环体被放入 while 循环体中,在第一个位之后。对你来说,它看起来像是foreach
一个真正的循环。实际上,这就像编译器的查找/替换练习。C# 中的很多东西都是这种方式——新特性和语法减少只是以旧方式执行代码的一种查找/替换方式。
为了使foreach
一个类不必实现任何接口或成为任何特定类型,它只需要有一个称为GetEnumerator()
返回“可以枚举的东西”的方法。
“可以枚举的东西”被定义为“具有返回任何类型对象的bool MoveNext()
方法和属性的类”。Current
同样,这个“可以枚举的东西”不必实现任何接口,或者是任何特定类型;它只需要一种方法和一种具有特定名称和特定签名的属性。整个事情就像魔术一样,在任何地方都没有限制:
public class ForeachableThing{
public EnumeratorSchmenumerator GetEnumerator(){
return new EnumeratorSchmenumerator();
}
}
public class EnumeratorSchmenumerator{
public DateTime Current {
get{ return DateTime.Now; }
}
public bool MoveNext() {
return DateTime.Now.Hour == 0;
}
}
您可以 foreach 数百万次以获取当前时间,介于午夜和凌晨 1 点之间。枚举不需要有集合或移动到任何地方;它只需要按要求返回值,并在被告知移动时返回 true 或 false。我概述了这一点,以防你认为“但肯定会有一些东西必须实现一些 IEnumerable.. 这意味着在某处有一些输入和..”。不 - 自从数据表被发明以来,就可以纯粹根据它们是否有某种方法/属性来枚举事物
跳到DataTable.Rows
; 这是一个集合;准确地说DataRowCollection
。它确实实现了IEnumerable
接口,因为它继承自InternalDataCollectionBase
,它实现IEnumerable
了 - 但它本身只是一个接口,它声明“类必须有一个GetEnumerator()
返回一个IEnumerator
”的方法,并且IEnumerator
是一个强制“必须有一个返回的Current
属性object
和MoveNext()
返回bool
".
没有必要实现这些接口foreach
,但它有帮助..
..也许你然后发现了它:实现IEnumerator
要求Current
属性是object
.
这是一个编译器错误:
public class EnumeratorSchmenumerator : IEnumerator //look! new bit!
{
public DateTime Current {
get{ return DateTime.Now; }
}
public bool MoveNext() {
return DateTime.Now.Hour == 0;
}
}
“EnumeratorSchmenumerator”未实现接口成员“IEnumerator.Current”。[现有] 'EnumeratorSchmenumerator.Current' 无法实现 'IEnumerator.Current' 因为它没有匹配的返回类型 'object'
因此,在选择使用该DataRowCollection
工具IEnumerable
时,他们被迫编写一个.GetEnumerator()
返回 an 的方法IEnumerator
,而这反过来又迫使 theCurrent
成为一个object
该对象内部有一个DataRow
,但编译器不知道,所以它键入var
as object
。
当您说foreach(DataRow r in dt.Rows)
C# 在幕后编写的代码以扩展时,foreach
将包括转换为DataRow
.
有了var
表格,就像你写的一样foreach(object r in dt.Rows)