Why are assignment operators (=) invalid in a foreach
loop? I\'m using C#, but I would assume that the argument is the same for other languages that support
You cannot modify a list that is being looped through via a "ForEach".
The best option is to simply create a temporary list to store the items you wish to use.
Because you can't use a foreach
loop to modify an array you're looping through. The loop iterates through the array, so if you try to modify what it's iterating through then unexpected behavior may occur. Furthermore, as Darin and DMan have pointed out, you're iterating through an IEnumerable
which is itself read-only.
PHP makes a copy of the array in its foreach
loop and iterates through that copy, unless you use references, in which case you'll modify the array itself.
It would be perfectly possible to let it be altered. However, what does this then mean? It would read like the underlying enumeration was modified, which it isn't (it would be possible to allow that too, but that has its own downsides).
So you'd have code that people would naturally read as indicating something other than what has actually happened. Considering that the purpose of a computer language is primarily to be understood by people (compilers deal with the balance being set against them, unless you use assembly, machine code, or the appropriately named Brainf**k) this would indicate a flaw in the language.
Here's your code:
foreach (string item in sArray)
{
item = "Some assignment.\r\n";
}
Here's a rough approximation of what the compiler does with this:
using (var enumerator = sArray.GetEnumerator())
{
string item;
while (enumerator.MoveNext())
{
item = enumerator.Current;
// Your code gets put here
}
}
The IEnumerator<T>.Current
property is read-only, but that's not actually relevant here, as you are attempting to assign the local item
variable to a new value. The compile-time check preventing you from doing so is in place basically to protect you from doing something that isn't going to work like you expect (i.e., changing a local variable and having no effect on the underlying collection/sequence).
If you want to modify the internals of an indexed collection such as a string[]
while enumerating, the traditional way is to use a for
loop instead of a foreach
:
for (int i = 0; i < sArray.Length; ++i)
{
sArray[i] = "Some assignment.\r\n";
}
Because an IEnumerable
is readonly.
In general, if you're trying to do this, you need to think long and hard about your design, because you're probably not using the best construction. In this case, the best answer would probably be
string[] sArray = Enumerable.Repeat("Some assignment.\r\n", 5).ToArray();
Higher level constructions are almost always usable instead of this kind of loop in C#. (And C++, but that's a whole other topic)