How to Modify a List in a 'Foreach' Loop

What is the best way to modify a list in a 'foreach' loop?

The collection used in foreach is immutable. This is very much by design.

As it says on MSDN:

The foreach statement is used to
iterate through the collection to get
the information that you want, but can
not be used to add or remove items
from the source collection to avoid
unpredictable side effects. If you
need to add or remove items from the
source collection, use a for loop.

The post in the link provided by Poko indicates that this is allowed in the new concurrent collections.

C# Modify List item while in a foreach loop

As I can see, you have emails in the friendsOnline:

string[] friendsOnline = new[] {
"Me@Shire.com",
"Dark.Lord@Mordor.gov",
};

and you want to change these emails into names:

string[] friendsOnline = new[] {
"Frodo Baggins",
"Sauron the Black",
};

First of all, I suggest executing query just once: SQL is too slow to be run in a loop; instead you can build a dictionary which eMail corresponds to which indexes:

using System.Linq;

...

// eMail - indexes correspondence
Dictionary<string, int[]> dict = friendsOnline
.Select((name, index) => (name : name, index : index))
.GroupBy(pair => pair.name, pair => pair.index, StringComparer.OrdinalIgnoreCase)
.ToDictionary(group => group.Key, group => group.ToArray());

// We take all users (no WHERE), but once
// We read both username and email
string sql =
@"SELECT `username`,
`email`
FROM `accounts`";

//DONE: using - we should Dispose IDisposable Command and Reader
using cmd = new MySqlCommand(sql, conn);
using rdr = cmd.ExecuteReader();

while (rdr.Read()) {
string name = Convert.ToString(rdr[0]);
string mail = Convert.ToString(rdr[1]);

// If we have correspondent indexes, we change friendsOnline
if (dict.TryGetValue(mail, out var indexes))
foreach (var index in indexes)
friendsOnline[index] = name;
}

Modifying list inside foreach loop

Rather than use a foreach construct, a for loop would allow you to alter the list.

for (var x = 0; x < list.Count; x++) {

}

How update a list in a foreach

Use for for modifing lists. NOT foreach.

As it says on MSDN:

The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.

        List<Envolvido> mylist = t.Result;

for (int index = 0; index < mylist.Count(); index++)
{
var items = mylist.ToList();
Envolvido envolvido = items[index];

envolvido.SUSPID= Convert.FromBase64String(envolvido.SUSPID);
envolvido.IVNOME = Convert.FromBase64String(envolvido.IVNOME);
}

How to modify list entries during for loop?

It's considered poor form. Use a list comprehension instead, with slice assignment if you need to retain existing references to the list.

a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)

ForEach will not alter/change items in list C#

You should use the Select function if you want to get a different result.

var items = listBox1.Items.Cast<string>().ToList();
listBox1.Items = items.Select(item => (!chkBox1.Checked) ? "move " + item : "move -check " + item).ToList();

The ForEach function can do something according to a collection value, but can't do it to the values themselves.

The Select function will create a new collection according to the given collection.

Edit

About your edit of successfully changing values by using

tapes.ForEach(x => x.vItem = "tapelib 3592 -eject " + x.vItem);

You need to understand how passing argument by value/reference works.

In c#, when writing var obj1 = new object(), obj1 is a pointer to the new object() that exists on the heap.

When you pass obj1 to a function public void Foo(object obj) { //... } by calling Foo(obj1), the function will get the parameter as new pointer to the same object on the heap.

Therefore, when you use ForeEach on the object itself,

object.ForEach(obj => obj = new object()) // No changed outside the Foreach

only the new pointer will be changed and it will point on a new object but the original pointer isn't changed.

But if you use it on an inner object,

object.ForEach(obj => obj.InnerObject = new object()) // Changed outside the Foreach

this will change the pointed inner object and the inner object will be changed.

Update ListT using foreach loop and Condition using LINQ/LAMBDA

foreach(var item in SeasonList.Where(x => x.Text == "ALL"))
{
item.Selected = false;
}


Related Topics



Leave a reply



Submit