如果listControl
是ListControl对象(如DropDownList),我很困惑为什么这段代码无法编译:
foreach (var item in listControl.Items) {
item.Value = string.empty;
}
编译器认为item
属于object
类型。如果我用var
替换ListItem
,明确声明变量,它就有效。 Items
属性为ListItemCollection
,实现IEnumerable
。编译器是否应该能够告诉集合中的对象是ListItem
类型的对象?
答案 0 :(得分:6)
这是一种奇怪的行为,因为正如您所指出的,ListItemCollection
是ListItem
的集合。这似乎与在C#支持的泛型之前实现的事实相关。因此它实现了IEnumerable
而不是IEnumerable<ListItem>
,并且无法确定正确的类型。
我建议用这种方式重写你的循环:
foreach (ListItem item in listControl.Items) {
item.Value = string.empty;
}
查看this question了解更多信息。
答案 1 :(得分:4)
编译器无法在编译时告诉您,因为这些项是对象。它将使用任何类型进行编译,例如,如果您使用
foreach(int item in collection)
它会编译,因为从object到int的转换是有效的,但它会在运行时抛出异常,因为类型不兼容。
答案 2 :(得分:1)
Items属性是一个ListItemCollection,它实现了IEnumerable。编译器不应该能够告诉集合中的对象是ListItem类型吗?
否。编译时类型为object
,因为这是IEnumerator.Current
的编译时类型。 var
关键字仍然是静态输入的!如果ListItemCollection
已实施IEnumerable<T>
而不是IEnumerable
,则编译器会了解更多信息。
... System.Collections.IEnumerator [is]用于从集合中获取项目。
当您使用foreach
循环时,您隐式使用IEnumerator接口。因此,当您访问每个项目时,Current
属性returns an object即使在运行时位于ListItem
下也是如此。
重要的是,var
关键字仍然是静态的,因此您可能编写了以下代码。您是否希望编译器能够理解这一点:
foreach (var item in (object)listControl.Items) {
item.Value = string.empty;
}
您的var
是静态类型的object
。如果您希望运行时确定它是ListItem,那么您必须使用dynamic
而不是var
。