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 foreach
(e.g. PHP). For example, if I do something like this:
string[] sArray = new string[5];
foreach (string item in sArray)
{
item = "Some assignment.\r\n";
}
I get an error, "Cannot assign to 'item' because it is a 'foreach iteration variable'."
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 the language specification says so.
But seriously, not all sequences are arrays or things that can be logically modified or written to. For instance:
foreach (var i in Enumerable.Range(1, 100)) {
// modification of `i` will not make much sense here.
}
While it would've been technically possible to have i = something;
modify a local variable, it can be misleading (you may think it really changes something under the hood and it wouldn't be the case).
To support these kind of sequences, IEnumerable<T>
doesn't require a set
accessor for its Current
property, making it read-only. Thus, foreach
cannot modify the underlying collection (if one exists) using the Current
property.
The foreach
loop is designed to iterate through objects in a collection, not to assign things- it's simply design of the language.
Also, from MSDN:
"This error occurs when an assignment to variable occurs in a read- only context. Read-only contexts include foreach iteration variables, using variables, and fixed variables. To resolve this error, avoid assignments to a statement variable in using blocks, foreach statements, and fixed statements."
The foreach keyword just enumerates IEnumerable instances (getting an IEnumerator instances by calling the GetEnumerator() method). IEnumerator is read-only, therefore values can't be changed using IEnumerator =can't be changed using the foreach context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With