BKR
BKR

Reputation: 443

List's ForEach() method not acting as expected

Why is this not working?

List<int> test = new List<int>();
for (int i = 0; i < 20; ++i)
    test.Add(i);

test.ForEach(t =>  t = ++t);

The elements in test are not incremented.

Upvotes: 2

Views: 348

Answers (5)

123 456 789 0
123 456 789 0

Reputation: 10865

List<int> test = new List<int>();
for (int i = 0; i < 20; ++i)
test.Add(i);
for(var z = 0 ; z < test.Count; z++)
{
    test[z]++;
}

Upvotes: 0

user7116
user7116

Reputation: 64148

This is the expected result.

You wouldn't expect the following to actually increment x in Main, so your lambda example is no different.

static void Main(string[] args)
{
    int x = 1;
    Increment(x);
    Console.WriteLine("{0}");
}

static void Increment(int x)
{
    x = ++x;
}

Upvotes: 1

Servy
Servy

Reputation: 203812

The t variable that you have is a copy of the item in the list. You are modifying a copy, and as such the item in the list itself isn't affected. To increment each item in the list you can use a for loop:

for(int i = 0; i < test.Count;i++
    test[i]++;

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1503439

Firstly, List<T>.ForEach isn't part of LINQ. It's been in .NET since 2.0.

Elements in test are not incremented

No, they wouldn't be. The parameter to Action<T> is passed by value, not by reference. Changes made to the parameter (t in your case) aren't visible to the calling code - and even if they were, there's no guarantee that List<T>.ForEach would use them.

Note that if you had a reference type (e.g. StringBuilder) as the list element type, and made changes to the data in the object that the parameter value referred to, e.g.

builders.ForEach(x => x.Append("Foo"))

then those changes would be visible in the list, because they're not changes to the list at all - the list would contain the same references as before, just to objects whose data happened to have changed.

Upvotes: 5

Vivek
Vivek

Reputation: 2123

Ints are values, not references.

Plus a foreach doesn't allow manipulation of the collection elements.

So it's a double fail i'm afraid :(

What would work:

for(int i=0;i<test.Count;i++)
    test[i]++;

Upvotes: 5

Related Questions