4

ListBox 控件具有ListItemCollectionItems类型的属性。

我有点明白为什么我不能写了

foreach (var item in ShipperListBox.Items)
{
    if (item.Selected) count++;
}

但是必须写

foreach (ListItem item in ShipperListBox.Items)
{
    if (item.Selected) count++;
}

它与ListItemCollection实施有关IEnumerable,而不是IEnumerable<ListItem>(如本问题所述)。

但我不明白为什么以下没有问题。

for (int i = 0; i < ListBox1.Items.Count; i++)
{
    if (ListBox1.Items[i].Selected) count++;
}

ListItemCollection 的哪一部分让编译器清楚的ListBox.Items[i]是 type ListItem

4

3 回答 3

1

因为ListItemCollection实现了一个返回ListItem.

这与IEnumerable.

于 2012-10-24T20:21:11.017 回答
0

这是明确存在的内容.OfType<ListItem>()的一部分:.Cast<ListItem>()

Cast(IEnumerable) 方法通过提供必要的类型信息,可以在非泛型集合上调用标准查询运算符。例如,ArrayList 没有实现 IEnumerable,但是通过在 ArrayList 对象上调用 Cast(IEnumerable),然后可以使用标准查询运算符来查询序列。(资源)

所以你可以写

foreach (var item in ShipperListBox.Items.OfType<ListItem>())
{
    if (item.Selected) count++;
}

不过,我不能告诉你为什么。

于 2012-10-24T20:22:00.000 回答
0

ListItemCollection.GetEnumerator 确实返回了一个自 .NET 1.0 以来使用的枚举器,它确实将对象作为值返回。foreach 模式(正如 Eric Lippert 详细解释的那样)需要对象通过 GetEnumerator 方法返回的 Enumerator。

当您使用 var 时,编译器将循环变量的类型推断为对象,因为 Enumerator 的 Current 确实只返回一个对象。

public interface IEnumerator
{
    bool MoveNext();
    object Current { get; }
    void Reset();
}

但是,当您使用foreach(ListItem item in xxx)... 时,编译器会自动为您从对象添加到 ListItem 的强制转换。您可以在执行 foreach(string str in new object[] { "str", 1 }) 时尝试一下,这将导致 InvalidCastException。var关键字没有魔法。它只是简单地推断类型而不做任何额外的魔术。

当您期望ListItem循环中有 a 时,您应该清楚地写出来。从枚举器的方法签名中不清楚它将返回什么对象。您必须告诉编译器您期望的类型。不使用 var 关键字的另一个原因是代码的读者也无法推断出循环变量的类型。

于 2012-10-24T21:11:51.970 回答