myGrid.Rows
是类型DataGridViewRowCollection
。
这东西很老了,它的定义是:
public class DataGridViewRowCollection : ICollection, IEnumerable, IList
你看到非通用接口了吗?这个类可以实现IList<DataGridViewRow>
,然后var
就可以工作,但它是遗留的。
IEnumerable
不传达有关项目类型的信息,并且该GetEnumerator
函数在这里没有帮助,因为它返回一个IEnumerator
,而它可以返回一个IEnumerator<DataGridViewRow>
。
本质上,C# 编译器寻找一个GetEnumerator
函数,该函数返回一个对象,该对象具有MoveNext
函数和Current
属性(或显式实现时的IEnumerable<T>
/IEnumerable
接口)。这种鸭子类型的方法是出于历史原因,它在泛型被引入语言之前就已经存在。循环变量将foreach
与Current
属性的类型相同。并且在IEnumerator
(非泛型变体)内,Current
是object
.
明确指定类型:
foreach (DataGridViewRow row in myGrid.Rows)
只是将返回值转换Current
为 a DataGridViewRow
,因为缺乏更好的机制。
如果您真的想在这里使用该var
关键字,您也可以使用 LINQ 来实现相同的效果:
foreach (var row in myGrid.Rows.Cast<DataGridViewRow>())
这是可行的,因为扩展方法返回一个,而后者又使用,并最终成为枚举数属性的类型,因此传播了类型信息。Enumerable.Cast<T>
IEnumerable<T>
IEnumerator<T>
T
Current
我怀疑此时您是否会从这些细节中受益,但是当您了解有关该语言的更多信息时,您可能希望保留此信息以供进一步参考。您必须了解扩展方法和泛型类型才能掌握这一点。