Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ForEach will not alter/change items in list C#

Tags:

c#

foreach

I'm pretty sure this has worked before in some code I have written, not sure what I am missing here.

The following code does not change the string values in my list. Why?

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

EDIT : Just to clarify, the list remains the same as when it was created.

EDIT : Apologies, the items list (listBox1.Items) contains alphanumeric strings as follows.

J00123456

J00123344

J00123458

Also, just to confirm, I have successfully done this with a custom list of T (shown below), which is why I thought it would work here.

var tapes = new List<TapeInfo>();
... //Populated list
tapes.ForEach(x => x.vItem = "tapelib 3592 -eject " + x.vItem);  //Works here
like image 539
Magic Mick Avatar asked Apr 28 '15 06:04

Magic Mick


People also ask

Can you use foreach on a list?

forEach statement is a C# generic statement which you can use to iterate over elements of a List.

How do I change the value of a foreach loop?

The value being iterated cannot be changed, because the foreach loop relies on the IEnumerator interface, and this interface has no method to change the value being enumerated. Also notice that values referred by the value being iterated can be changed (but not the value being iterated).

Can we use foreach on list in C#?

In C#, the foreach loop iterates collection types such as Array, ArrayList, List, Hashtable, Dictionary, etc. It can be used with any type that implements the IEnumerable interface. The following example demonstrates iteration of an array using a foreach loop.

Can we modify list while iterating C#?

Yes, that is a very important point, and all programmers should think about this very carefully. As a general rule in programming, you should avoid mutating an object while iterating over it, unless it is the specific purpose of the function to mutate the original object.


2 Answers

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.

like image 65
motcke Avatar answered Sep 17 '22 08:09

motcke


strings are immutable, so they cannot be changed. Assigning another value to that variable only changes that variable (difference between call-by-reference and call-by-value).

When you use the ForEach-method, you actually iterate over your items-list using the item-variable declared in your lambda-expression. Assigning a different value to that variable, cannot change the list.

And to have it clear what my first sentence means: You cannot change the value of your variable, because it's immutable, so you assign the variable, which cannot take affect to the list.

like image 41
Patrik Avatar answered Sep 18 '22 08:09

Patrik