问题
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
回答1:
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.
回答2:
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.
回答3:
Foreach simply can't do it, since item
is a local variable within the loop's scope.
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 a 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;
}
That's assuming, of course, that the items are and should be strings. I've also improved readability of your ternary condition.
来源:https://stackoverflow.com/questions/29911734/foreach-will-not-alter-change-items-in-list-c-sharp