views:

493

answers:

2

I have the following Generic List which is populated with a list of string:

List<string> mylist =new List<string>();  
myList.add("string1");  
myList.add("string2");

Say I want to add 'test' at the end of each string, how can I do it in a simple way? Intuitively, I tried this which compiles ok:

myList.ForEach(s => s = s + "test");

But if I then look at the content of the List, nothing has changed. I guess I could use a for loop to iterate through the List but I'm looking for something very simple and using ForEach looks very neat.... but doesn't seem to work. Any ideas?

+5  A: 

It's not possible to do that unless the list type is a mutable reference type (and in that case, you can't still change the actual reference in the list but the object itself).

The reason is that List<T>.ForEach calls a Action<T> delegate with signature:

delegate void Action<T>(T obj);

and here, the argument is passed by value (it's not ref). Like any method, you can't change the input argument when it's called by value:

The code is essentially equivalent to:

void anonymous_method(string s) {
    s = s + "test";  // no way to change the original `s` inside this method.
}

list.ForEach(anonymous_method);
Mehrdad Afshari
Thanks for the explanation. Very useful.
Anthony
I also thank ye' for the explanation... That's the simplest straigth-up explanation I've seen... beats anything and everything on MSDN hands down. Ta.
corlettk
+4  A: 

The problem is that the Action you specified gets executed on the elements of the list, but the result is not put back anywhere... your s is a local variable only.

Changing the list in-place will probably take an actual foreach, but if you are happy to take a new list as the result, you could try:

list = list.ConvertAll(s => s + "test");

Not quite the same... but as close as you'll get...

jerryjvl