I have a foreach loop that needs converting to a for or while loop. My loop looks like this:
foreach (Item item in Items)
{
// some stuff
}
What is the equivalent for or while loop?
I think I need to use GetEnumerator to get an IEnumerator<Item>, but I don't know how to use it properly. Items isn't a list, otherwise I'd use indexing.
In the simplest case(no disposing etc.) you can use:
var enumerator = Items.GetEnumerator();// `var` to take advantage of more specific return type
while(enumerator.MoveNext())
{
Item item = enumerator.Current;
...
}
For the exact rules check the C# specification 8.8.4 The foreach statement.
A foreach statement of the form
foreach (V v in x) embedded-statement
is then expanded to:
{
E e = ((C)(x)).GetEnumerator();
try {
V v;
while (e.MoveNext()) {
v = (V)(T)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
(Quoted from the C# Language Specification Version 4.0)
The types using here are: "a collection type C, enumerator type E and element type T". E is the return type of GetEnumerator, and not necessarily IEnumerator<V> since foreach uses duck typing. The spec also describes a number of corner cases and how to infer these types, but those details are probably not relevant here.
In C# 5 the declaration of v will be moved into the while loop to get more intuitive closure semantics.
If you're going to use a for loop, it generally means there's some way of quickly accessing the n-th item (usually an indexer).
for(int i = 0; i < Items.Count; i++)
{
Item item = Items[i]; //or Items.Get(i) or whatever method is relevant.
//...
}
If you're just going to access the iterator, you usually just want to use a foreach loop. If, however, you can't, this is usually the model that makes sense:
using(IEnumerator<Item> iterator = Items.GetEnumerator())
while(iterator.MoveNext())
{
Item item = iterator.Current;
//do stuff
}
you could, technically, do this in a for loop, but it would be harder because the construct just doesn't align well with this format. If you were to discuss the reason that you can't use a foreach loop we may be able to help you find the best solution, whether or not that involves using a for loop or not.
This is an equivalent in a for-loop
for (IEnumerator i = Items.GetEnumerator(); i.MoveNext(); )
{
Item item = (Item)i.Current;
// some stuff
}
Related
so far I have done this:
List<string[]> VList
foreach (var item in VList)
{
foreach (var b in item)
{
Richtextbox 1 = VList[item][b]?
}
}
How do I do this correct? I want it to write everything that the list contains
A foreach loop iterates a collection1 using an IEnumerator1.
In each iteration, the loop variable (item and b in your case) references whatever the IEnumerator.Current property is referencing.
The square brackets [] are used for a special kind of property called indexers. Indexers are typically used in a collection2 to provide a reference to whatever the collection is holding that is coupled to that specific index.
When you are using a foreach loop, you don't need to know the index of an element in the collection - and in fact, the collection doesn't even have to support indexes - you already have a reference to it via the loop variable.
So a code that uses a nested foreach loop to do something with the strings inside a variable of type List<string[]> would be something like this:
foreach(var stringArray in VList)
{
foreach(var str in stringArray)
{
// do something with str here...
}
}
If you want to use indexers, use a for loop instead:
for(var i=0; i<VList.Count; i++)
{
for(var j=0; j<VList[i].Length; j++)
{
// do something with VList[i][j] here...
}
}
1 Actually, a foreach loop doesn't need an actual collection to work with.
It only needs an instance that has a method called GetEnumerator() that returns an object that has a public property called Current and a public method called MoveNext.
This means that even if you have a class that doesn't implement the IEnumerable interface but has the GetEumerator method, and that method returns an instance of some other class that doesn't implement the IEnumerable interface but has the Current property and the MoveNext method, you can still use foreach with that. This is called duck typing.
This is documented in foreach, in (C# reference)
2 The fact that a type has indexer doesn't have to mean that the type is a collection - it's perfectly valid to add indexres to your own type without implementing any interface collections usually implement such as IEnumerable or ICollection.
Your access is wrong. You are iterating over the elements there is no need to use the array/indexer access. []
List<string[]> VList
foreach (var item in VList)
{
foreach (var b in item)
{
Richtextbox1.text += b
}
}
Why we can iterate item ex
mList.ForEach((item)
{
item.xyz ....
}
and for a simple array we need to force foreach loop?
foreach(int i in arr)
i.xyz
or use delegate type ?
Action<int> action = new Action<int>(myfunc);
Array.ForEach(intArray, action);
What is the differemce?
The first syntax is not correct. It should be like this:
mList.ForEach(item =>
{
// item.xyz
});
The ForEach is a method of List<T> that enables you for each item in a list to call an Action<T>.
On the other hand the foreach
statement repeats a group of embedded statements for each element in
an array or an object collection that implements the
System.Collections.IEnumerable or
System.Collections.Generic.IEnumerable interface.
That being said, ForEach can be called only on lists and foreach can be called on any object that implements either IEnumerable or IEnumerable. That's the big difference here.
Regarding the delegate type, there isn't any difference. Actually, lambda expressions item=>{ item.xyz = ...} are a shorthand for delegates.
The language defines foreach as an operation of IEnumerable. Therefore, everything which implements IEnumerable is iteratable. However, not all IEnumerables 'make sense' when using a ForEach block.
Take this for example:
public static IEnumerable<MyObject> GetObjects()
{
var i = 0;
while(i < 30)
yield return new MyObject { Name = "Object " + i++ };
}
And then you do something like this:
var objects = GetObjects();
objects.ForEach(o => o.Name = "Rob");
foreach (var obj in objects)
Console.WriteLine(obj.Name);
IF that compiled, it would print out Object 0 to Object 29 - NOT Rob 30 times.
The reason for this is that the iterator is reset each time you iterate the enumerable. It makes sense for ForEach on a list, as the enumerable has been materialized, and objects are not re-created every time you iterate it.
In order to make ForEach work on an enumerable, you'd need to materialize the collection as well (such as putting it into a list), but even that is not always possible, as you can have an enumerable with no defined end:
public static IEnumerable<MyObject> GetObjects()
{
while(true)
yield return new MyObject { Name = "Object " };
}
It also makes sense to have ForEach on Array - but for reasons I'm unaware of, it was defined as Array.ForEach(arr) rather than arr.ForEach()
Moral of the story is, if you think you need a ForEach block, you probably want to materialize the enumerable first, usually to a List<T> or an array (T[]).
A ListBox control has an Items property of type ListItemCollection.
I sort of understand why I can't write
foreach (var item in ShipperListBox.Items)
{
if (item.Selected) count++;
}
But instead have to write
foreach (ListItem item in ShipperListBox.Items)
{
if (item.Selected) count++;
}
It has to do with ListItemCollection implementing IEnumerable and not IEnumerable<ListItem> (as explained in this question).
But what I don't get is why the following is no problem.
for (int i = 0; i < ListBox1.Items.Count; i++)
{
if (ListBox1.Items[i].Selected) count++;
}
What part of ListItemCollection is making it clear to the compiler that ListBox.Items[i] is of type ListItem?
Because ListItemCollection implements an indexer that returns a ListItem.
This is separate from IEnumerable.
This is part of what .OfType<ListItem>() and .Cast<ListItem>() explicitly exist for:
The Cast(IEnumerable) method enables the standard query operators to be invoked on non-generic collections by supplying the necessary type information. For example, ArrayList does not implement IEnumerable, but by calling Cast(IEnumerable) on the ArrayList object, the standard query operators can then be used to query the sequence. (source)
So you can write
foreach (var item in ShipperListBox.Items.OfType<ListItem>())
{
if (item.Selected) count++;
}
I couldn't tell you why, though.
ListItemCollection.GetEnumerator does return an enumerator which was used since .NET 1.0 which does return object as value. The foreach pattern (as Eric Lippert does explain in much greater detail) requires an Enumerator returned by the object via the GetEnumerator method.
When you use var the compiler infers the type of you loop variable as object since Current of the Enumerator does return only an object.
public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}
But when you use foreach(ListItem item in xxx) ... the compiler does add a cast to ListItem from object automatically for you. You can try it out when you do a foreach(string str in new object[] { "str", 1 }) which will result in an InvalidCastException. There is no magic going with the var keyword. It simply does infer the type without doing any extra magic.
When you expect a ListItem in your loop you should write it out clearly. From the method signature of the enumerator it is not clear what objects it will return. You have to tell the compiler which types you expect. One more reason to not use the var keyword since the readers of your code will also not be able to deduce the type of your looping variable as well.
for example:
1.
foreach (var item in myDic)
{
if (item.value == 42)
myDic.remove(item.key);
}
would the iterator works properly no matter how the statements in the inner brackets could possibly affect myDic?
2.
var newDic = myDic.where(x=>x.value!=42).ToDictionary(x=>x.key,x=>x.value);
Is 2nd approach a good practice? functional programming and immutable?
The first approach will crash at runtime, since the enumerator makes sure that nobody deletes from the underlying collection while it's enumerating.
The second approach is a nice thought, but C# dictionaries are mutable and it's neither idiomatic nor efficient to copy them around if you can accomplish the same thing with mutation.
This is a typical way:
var itemsToRemove = myDic.Where(f => f.Value == 42).ToArray();
foreach (var item in itemsToRemove)
myDic.Remove(item.Key);
EDIT: In response to your question in the comments. Here's how the example in your other question works:
myList = myList.where(x=>x>10).select(x=>x-10);
This line of code doesn't run anything; it's totally lazy. Let's say for the sake of argument that we have a foreach after it to make it look more like this question's example.
foreach (int n in myList)
Console.WriteLine(n);
When that executes, here's what'll happen on each iteration:
Call MoveNext on the enumerator
The enumerator finds the next value greater than ten
Then it takes that value minus ten and sets the Current property to that
Binds the Current property to the variable n
Console.WriteLines it
You can see that there's no mystery and no infinite loop and no whatever.
Now compare to my example, supposing we left out the ToArray.
var itemsToRemove = myDic.Where(f => f.Value == 42);
foreach (var item in itemsToRemove)
myDic.Remove(item.Key);
Call MoveNext on the enumerator
The enumerator finds the next pair with value 42 and sets the Current property to that
Binds the Current property to the variable item
Removes it
This doesn't work because while it's perfectly fine to WriteLine something from a collection while you have an enumerator open on it, you aren't permitted to Remove something from a collection while you have an enumerator open on it.
If you call ToArray up front, then you start out by enumerating over the dictionary and populating the array. When we get to the foreach, the foreach statement has an enumerator open on the array, not the dictionary. You're allowed to remove from the dictionary as you iterate over the array.
Also you can iterate over the copy of your collection:
foreach (var item in myDic.ToList())
{
if (item.value == 42)
myDic.remove(item.key);
}
notice myDic.ToList() in foreach statement.
According to the docs, starting from .NET Core 3.0, removing an element will no longer affect active enumerators. You can safely remove an item while iterating:
foreach (var item in myDic)
{
if (item.Value == 42)
myDic.Remove(item.Key);
}
Dictionary<TKey,TValue>.Remove Method
.NET Core 3.0+ only: this mutating method may be safely called without invalidating active enumerators on the Dictionary<TKey,TValue> instance. This does not imply thread safety.
I would suggest making a copy of the keys and not the entire dictionary as an array, like others have suggested.
mykeytype[] mykeys = new mykeytype[mydic.Keys.Count];
mydic.Keys.CopyTo(mykeys, 0);
foreach (var key in mykeys)
{
MyType thing;
if (!mydic.TryGetValue(key, out thing)) continue;
// remove or add to dictionary here
}
As I was refactoring some code this morning, I noticed some weird behavior. I was iterating over a collection of type A. The declaration and usage of the Enumerable were split (I was declaring and defining a variable using some Linq, then iterating over it later via foreach). However, when I changed the type of the enumerable from IEnumerable<A> to IEnumerable<B>, I left the foreach as the following where enumerable was of type IEnumerable<B>.
IEnumerable<B> enumerable = someEnumerableOfB
foreach(A a in enumerable)
Following is a contrived example of the behavior I found:
IEnumerable<IEnumerable> enumerables = Enumerable.Range(1, 5).Select(x => new List<int> { x });
foreach (StringComparer i in enumerables) //this compiles
{
//do something here
}
foreach (int i in enumerables) //this doesn't compile
{
//do something here
}
IEnumerable<StringBuilder> stringBuilders = Enumerable.Range(1, 5).Select(x => new StringBuilder(x.ToString()));
foreach (FileStream sb in stringBuilders) //this doesn't compile
{
//do something here
}
I was surprised to see the first one compile. Can someone explain exactly why this works? I assume it has something to do with the fact that the IEnumerable is of an interface, but I can't explain it.
According to the algorithm described section §15.8.4. of the specification, the compiler will expand the foreach into the following:
{
IEnumerator<IEnumerable> e = ((IEnumerable<IEnumerable>)(x)).GetEnumerator();
try
{
StringComparer v;
while (e.MoveNext())
{
v = (StringComparer)(IEnumerable)e.Current; // (*)
// do something here
}
}
finally
{
// Dispose of e
}
}
The line I've marked with an asterisk is the reason why it compiles for the first and not for the second. That is a valid cast because you can have a subclass of StringComparer that implements IEnumerable. Now change it to:
v = (int)(IEnumerable)e.Current; // (*)
And it doesn't compile, because this is not a valid cast: int does not implement IEnumerable, and it can't have any subclasses.
Because the compiler cant know whats in the Enumerable but it knows that it cant be a value type (e.g. int).
foreach (StringComparer i in enumerables) will compile since StringComparer is a reference type and for the compilers sake might just be in enumerables.