Using Array.Foreach to modify the collection

Asked

Viewed 842 times

4

I want to remove spaces from the beginning and end of the string (Trim) in all positions of array, but none of the ways below worked.
What am I doing wrong?

var optionArray = new string[] { "in the jungle ", " the mighty jungle", " the lion sleeps tonight " };

Array.ForEach(optionArray, x => x.Trim()); // nada acontece
Array.ForEach(optionArray, x => x = x.Trim()); // nada acontece
optionArray = Array.ForEach(optionArray, x => x = x.Trim()); // Cannot implicitly convert type 'void' to 'string[]'

var optionList = optionArray.ToList();

optionList.ForEach(x => x.Trim()); // nada acontece
optionList.ForEach(x => x = x.Trim()); // nada acontece
optionList = optionList.ForEach(x => x = x.Trim()); // Cannot implicitly convert type 'void' to 'System.Collections.Generic.List<string>'
  • 3

    Look at this reply to understand why the Foreach does not work when you want to change a list value. It refers to Java but the same applies to C#.

2 answers

5


Daniel complementing Maniero’s response, the Eric Lippert in 2009 he wrote a good article in his blog, in it it explains the evils of using the List<T>.ForEach in place of foreach. You can read the article in full at the following link.: "foreach" vs "foreach"

Another argument would be that Micrsoft’s own architects decided not to include a method ForEach at Linq, you can read about the subject at.: Why no Foreach method on Ienumerable interfaces

but in short, you should not use the List<T>.ForEach, why it violates the principles of functional programming and may cause some side effects. besides, the List<T>.ForEach is less readable and this may imply a more difficult maintenance (try debug an iteration within a List<T>.ForEach).

Still, this is a scenario where this kind of implementation can be useful, parallelism... and yet there is a whole Namespace for this purpose: https://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel(v=vs.110). aspx

var lista = Enumerable.Range(1, 10).ToList();
Parallel.ForEach(lista, (item, state, indice) => {
    Console.WriteLine(string.Format("indice: {0}, value: {1}", indice, item));
});

but the implementation will still suffer from the same problem, you will not be able to modify the list, in this case you need to make use of the Parallel.For and access the element by the index.:

var lista = Enumerable.Range(1, 10).ToList();
Parallel.For(0, lista.Count, (indice, state) => {
    lista[indice] *= 2;
});

foreach(var item in lista) {
    Console.WriteLine(string.Format("value: {0}", item));
}

I put in the Github for future reference.

And finally, a good reason not to use the .Select(s => s.Trim()).ToArray(), you are not modifying the values of array. You are creating a new array with the new values, at this point you will have two arrays in memory, then will be just wasting memory, CPU cycles and forced that the Garbage Collector be called more often.

2

  • Unable to change collection with ForEach? It seems that this is done in an example of Dotnetpearls. Why would you do it the "manual way"?

  • Daniel, he is not changing the value of the items in the collection, he is simply "logging into the console" the values as he goes through each item. It would work for you if you just wanted to log this value, for example: optionList.Foreach(x => { Console.Writeline(x.Trim()) }); This would log the values without space, but not modify the array.

  • It is not possible, the element is not passed by reference, so it is not changed in the array. I might, but I’d have to create another array also. If you really want to use a method and lambda prefer to use LINQ, is more modern and does what you want. I would even foreach even.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.