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
forEach statement is a C# generic statement which you can use to iterate over elements of a List.
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).
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.
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.
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.
string
s 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.
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