List<T>.ForEach Method
.NET Framework 4
Performs the specified action on each element of the List<T>.
Assembly: mscorlib (in mscorlib.dll)
| Exception | Condition |
|---|---|
| ArgumentNullException |
action is null. |
The following example demonstrates the use of the Action<T> delegate to print the contents of a List<T> object. In this example the Print method is used to display the contents of the list to the console.
Note
|
|---|
|
In addition to displaying the contents using the Print method, the C# example demonstrates the use of anonymous methods to display the results to the console. |
using System; using System.Collections.Generic; class Program { static void Main() { List<String> names = new List<String>(); names.Add("Bruce"); names.Add("Alfred"); names.Add("Tim"); names.Add("Richard"); // Display the contents of the list using the Print method. names.ForEach(Print); // The following demonstrates the anonymous method feature of C# // to display the contents of the list to the console. names.ForEach(delegate(String name) { Console.WriteLine(name); }); } private static void Print(string s) { Console.WriteLine(s); } } /* This code will produce output similar to the following: * Bruce * Alfred * Tim * Richard * Bruce * Alfred * Tim * Richard */
Windows 7, Windows Vista SP1 or later, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (Server Core not supported), Windows Server 2008 R2 (Server Core supported with SP1 or later), Windows Server 2003 SP2
The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
Variable Capture
Another difference between this ForEach method and a proper foreach loop, in C# 4 anyway, is that it behaves differently when you capture the iteration variable in a lambda, anonymous function, or LINQ query.
The classic example:
List<int> values = Enumerable.Range(0,10).ToList();
var actions = new List<Action>();
foreach(int i in values) { actions.Add(() => Console.WriteLine(i)); }
foreach(Action a in actions) { a(); }
This code prints 9 ten times because in C# 4, there is only one 'i' variable which is shared by every delegate, so they all print the final value of it (which is 9) when they execute.
The Foreach method equivalent behaves differently:
values.ForEach(i => actions.Add(() => Console.WriteLine(i)));
This has a new variable 'i' on each iteration, which is captured separately by the inner lambda, so the code prints out the numbers from 0 to 9, not just 10 9s.
I have read that C# 5 will change the foreach statement's behavior to match this method, which is all to the good. Until then, this is a reason you might prefer the ForEach method.
The classic example:
List<int> values = Enumerable.Range(0,10).ToList();
var actions = new List<Action>();
foreach(int i in values) { actions.Add(() => Console.WriteLine(i)); }
foreach(Action a in actions) { a(); }
This code prints 9 ten times because in C# 4, there is only one 'i' variable which is shared by every delegate, so they all print the final value of it (which is 9) when they execute.
The Foreach method equivalent behaves differently:
values.ForEach(i => actions.Add(() => Console.WriteLine(i)));
This has a new variable 'i' on each iteration, which is captured separately by the inner lambda, so the code prints out the numbers from 0 to 9, not just 10 9s.
I have read that C# 5 will change the foreach statement's behavior to match this method, which is all to the good. Until then, this is a reason you might prefer the ForEach method.
- 3/21/2012
- Daniel Normal Johnson
Concurrent Modification
There's a big differnce between this ForEach method and a foreach loop in C# or VB: the foreach loop winds up checking for concurrent modification. That is, if anything alters the list while you are looping over it, the List's enumerator implementation will throw an InvalidOperationException.
This does not happen with this here ForEach method. If you modify the list from inside the Action<T>, no exception occurs. The list may misbehave in this case: I've seen it just loop forever, but it does not seem to ever throw.
I expect this checking is the reason why this ForEach method is actually faster than a proper foreach loop, even for a small list. I've done tests where this method runs faster than a loop for a 10-element list, which shows just how cheap that action delegate is. This is surprising: you'd expect the allocation and the virtual dispatch involved in using a delegate to weight more heavily, but it seems to not be the case.
This does not happen with this here ForEach method. If you modify the list from inside the Action<T>, no exception occurs. The list may misbehave in this case: I've seen it just loop forever, but it does not seem to ever throw.
I expect this checking is the reason why this ForEach method is actually faster than a proper foreach loop, even for a small list. I've done tests where this method runs faster than a loop for a 10-element list, which shows just how cheap that action delegate is. This is surprising: you'd expect the allocation and the virtual dispatch involved in using a delegate to weight more heavily, but it seems to not be the case.
- 3/21/2012
- Daniel Normal Johnson
Why not use Console.Writeline directly without the print method?
At least this works for me in Visual Studio 2010:names.ForEach(Console.WriteLine);
- 4/12/2011
- Matti Pastell
Note