为什么ListItem必须在foreach C#中显式声明
本文关键字:声明 foreach ListItem 为什么 | 更新日期: 2024-09-19 14:03:46
如果listControl
是ListControl对象(如DropDownList:),我很困惑为什么不编译此代码
foreach (var item in listControl.Items) {
item.Value = string.empty;
}
编译器认为item
属于object
类型。如果我用ListItem
替换var
,并显式声明变量,那么它就可以工作了。Items
属性是实现IEnumerable
的ListItemCollection
。难道编译器不应该知道集合中的对象是ListItem
类型的吗?
这是一个奇怪的行为,因为正如您所指出的,ListItemCollection
是ListItem
s的集合。这似乎与这是在C#支持泛型之前实现的事实有关。因此,它实现了IEnumerable
而不是IEnumerable<ListItem>
,并且无法确定正确的类型。
我建议这样重写你的循环:
foreach (ListItem item in listControl.Items) {
item.Value = string.empty;
}
查看此问题以了解更多信息。
编译器在编译时无法告诉您这一点,因为这些项是对象。它将使用任何类型进行编译,例如,如果您使用
foreach(int item in collection)
它将进行编译,因为从object到int的强制转换是有效的,但它将在运行时抛出异常,因为类型不兼容。
原始问题
Items属性是ListItemCollection,它实现IEnumerable。难道编译器不应该判断集合中的对象属于ListItem类型吗?
简短回答
没有编译时类型是object
,因为它是IEnumerator.Current
的编译时类型。var
关键字仍然是静态键入的!如果ListItemCollection
实现了IEnumerable<T>
而不是IEnumerable
,那么编译器将知道更多。
更多详细信息
来自文档:
a系统。集合。IEnumerator[用于从集合中获取项。
当您使用foreach
循环时,您隐含地使用IEnumerator接口。因此,当您访问每个项时,Current
属性返回一个对象,即使它在运行时是下面的ListItem
。
重要的是,var
关键字仍然是静态的,因此您可能已经编写了以下代码。你希望编译器能解决这个问题吗:
foreach (var item in (object)listControl.Items) {
item.Value = string.empty;
}
您的var
是一个静态类型的object
。如果您希望运行时确定它是ListItem,那么您必须使用dynamic
而不是var
。