Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Modify array or collection with foreach

I noticed something interesting. I can change the elements of the array or assign a new array reference in foreach blocks, but I cannot do the same operations with collections, it gives an error. Why??
The following example gives an error

List<string> isimler = new List<string>() { "Ali", "AyĹźe", "Fatma", "Mehmet" };

foreach (var (isim, index) in isimler.Select((isim, index) => (isim, index)))
{
    isimler[index] += 10;
}

foreach(string isim in isimler)
{
    Console.WriteLine(isim);
}

The following example does not give an error, It’s working

string[] isimler = { "Ali", "AyĹźe", "Fatma", "Mehmet" };

foreach (var (isim, index) in isimler.Select((isim, index) => (isim, index)))
{
    isimler[index] += 10;
}

foreach(string isim in isimler)
{
    Console.WriteLine(isim);
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Because lists have code for explicit tracking for this (changing a tracking integer every time you make a change through the list API), and arrays do not. In the case of lists, this is especially important because if you add or remove elements it could significantly adversely impact the behaviour of the loop (imagine removing the zeroth element, for example). Since you cannot add/remove with arrays, this is less of a concern, and arrays are intended as very raw data types, without the overhead of such additional tracking fields.

As it happens there are APIs you could use with List<T> to have this specific change not be noticed. That doesn’t make it a good idea to do so!

// DO NOT EVER DO THIS! Bad code! Only for illustration!
// This has *significant* risk of data corruption if you don't know
// **exactly** what you're doing.
var span = CollectionsMarshal.AsSpan(isimler);
foreach (var (isim, index) in isimler.Select((isim, index) => (isim, index)))
{
    span[index] += 10;
}

Ultimately, though, in either event: if the contents of something are changing while you’re looking at it: something risky is happening, whether or not it gets noticed.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading