Implicit typing in a ListItemCollection is not possible using foreach, but is possible with a for loop

The ListBox control has an Items property of type ListItemCollection .

I understand why I can not write

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

But instead you need to write

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

This is due to the ListItemCollection implementation of IEnumerable , not IEnumerable<ListItem> (as described in this question ).

But I do not understand why the following is not a problem.

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

What part of the ListItemCollection makes it clear to the compiler that ListBox.Items[i] is of type ListItem ?

+4
source share
3 answers

Because ListItemCollection implements an indexer that returns a ListItem .

Separated from IEnumerable .

+1
source

This is part of what .OfType<ListItem>() and .Cast<ListItem>() explicitly exist for:

The Cast (IEnumerable) method allows you to run standard query operators in non-general collections, providing the necessary type information. For example, an ArrayList does not implement IEnumerable, but by calling Cast (IEnumerable) on an ArrayList, standard queries can be used to query the sequence. (a source)

So you can write

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

I could not tell you why.

0
source

ListItemCollection.GetEnumerator returns the counter that was used with .NET 1.0, which returns the object as a value. The foreach pattern (as Eric Lippert explains in much more detail) requires the Enumerator object to be returned by the GetEnumerator method.

When you use var, the compiler introduces the type of the loop variable as an object, since Current of Enumerator returns only the object.

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

But when you use foreach(ListItem item in xxx) ..., the compiler automatically adds the cast to ListItem from the object for you. You can try when you do foreach (string str in the new object [] {"str", 1}), which will result in an InvalidCastException. There is no keyword var . It just concludes the type without too much magic.

When you expect a ListItem in your loop, you should write it clearly. It is not clear from the signature of the enumerator method which objects it will return. You must tell the compiler what types you expect. Another reason not to use the var keyword is because readers of your code will also not be able to infer the type of your loop variable.

0
source

Source: https://habr.com/ru/post/1441906/


All Articles