ForEach will not change / change items in a C # list

I am pretty sure that this worked before in some code that I wrote, not sure if I'm missing here.

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

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

EDIT : just for clarification, the list remains the same as when it was created.

EDIT . Sorry, the list of items (listBox1.Items) contains alphanumeric strings as follows.

J00123456

J00123344

J00123458

Also, just for confirmation, I successfully did this with a custom T list (shown below), so 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 
+5
source share
3 answers

You must use the Select function if you want 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 the value of the collection, but it cannot do it with the values ​​themselves.

The Select function will create a new collection in accordance with this collection.

Edit

About your change of successful value changes with

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

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

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

When you pass obj1 to the public void Foo(object obj) { //... } function public void Foo(object obj) { //... } by calling Foo(obj1) , the function will receive the parameter as a 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 to the new object, but the original pointer will not be changed.

But if you use it on an internal 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 resized.

+6
source

string are immutable, so they cannot be changed. Assigning this variable to a different value only changes this variable (the difference between calling by reference and callsign).

When you use the ForEach method, you actually iterate over your items -list with the item -variable declared in your lambda expression. Assigning another value to this variable cannot change the list.

And to make it clear what my first sentence means: you cannot change the value of your variable because it is immutable, therefore you assign a variable that cannot affect the list.

+4
source

Foreach simply cannot do this, since item is a local variable within the scope of the loop.
What you have is basically the same as using the long version:

 foreach(string item in listBox1.Items.Cast<string>().ToList()) { item = (!chkBox1.Checked) ? "move " + item : "move -check " + item; } 

you can use the for loop to achieve your goal:

 string Item; for(var i=0;i < listBox1.Items.Count; i++) { Item = listBox1.Items[i].ToString(); // Listbox Items are objects, so you need to use ToString() here listBox1.Items[i] = (chkBox1.Checked) ? "move -check " + Item : "move " + Item; } 

This assumes, of course, that the elements are and should be strings. I also improved the readability of your ternary state.

+4
source

All Articles