Reputation: 3317
(edit: Slight tidy of the code.)
Using foreach like this works fine.
var a = new List<Vector2>();
a.ForEach(delegate(Vector2 b) {
b.Normalize(); });
The following however causes "No overload for method 'ForEach' takes 1 arguments".
byte[,,] a = new byte[2, 10, 10];
a.ForEach(delegate(byte b) {
b = 1; });
Upvotes: 5
Views: 1899
Reputation: 5404
I would recommend you just use a normal foreach
loop to transform the data. You're using a method that exists only on the List<T>
implementation, but not on arrays.
Using a method for foreach
really gains you nothing, unless for some reason you were wanting to do data mutation in a method chain. In that case, you may as well write your own extension method for IEnumerable<T>
. I would recommend against that, though.
Having a separate foreach
loop makes it clear to the reader that data mutation is occurring. It also removes the overhead of calling a delegate for each iteration of the loop. It will also work regardless of the collection type as long as it is an IEnumerable
(not entirely true, you can write your own enumerators and enumerables, but that's a different question).
If you're looking to just do data transformations (i.e. projections and the like) then use LINQ.
Also keep in mind that with the array, you're getting a copy of the byte
not a reference. You'll be modifying just that byte
not the original. Here's an example with the output:
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
Array.ForEach(numbers, number => number += 1);
foreach(int number in numbers)
{
Console.WriteLine(number);
}
Which yields the output:
1 2 3 4 5
As you can see, the number += 1 in the lambda had no effect. In fact, if you tried this in a normal foreach
loop, you would get a compiler error.
Upvotes: 3
Reputation: 24192
I don't know of a ForEach method that takes multi-dimensional arrays. If you want one, i think you will have to create it yourself.
Here is how to do it:
private static void ForEach<T>(T[, ,] a, Action<T> action)
{
foreach (var item in a)
{
action(item);
}
}
Sample program, using the new ForEach method:
static class Program
{
static void Main()
{
byte[, ,] a = new byte[2, 10, 10];
ForEach(a, delegate(byte b)
{
Console.WriteLine(b);
});
}
private static void ForEach<T>(T[, ,] a, Action<T> action)
{
foreach (var item in a)
{
action(item);
}
}
}
Also, the ForEach
method in the Array
version, is not an instance method, it is statis method. You call it like this:
Array.ForEach(array, delegate);
Upvotes: 1
Reputation: 21878
raw arrays have much less instance methods than generic collections because they are not templated. These methods, such as ForEach()
or Sort()
are usually implemented as static methods which are themselves templated.
In this case, Array.Foreach(a, action)
will do the trick for the array.
Of course, the classical foreach(var b in a)
would work for both List and Array since it only requires an enumerator.
However:
(b=1)
won't work. Because you receive a value, not a reference.Upvotes: 0
Reputation: 62504
You've used syntax of List.ForEach()
method for the array, but Array.ForEach()
syntax is:
public static void ForEach<T>(
T[] array,
Action<T> action
)
One important point that array should be one-dimensional in order to use it in Array.ForEach()
. Considering this I would suggest using simple for
loop
// first dimension
for (int index = 0; index < bytesArray.GetLength(0); index++)
// second dimension
for (int index = 0; index < bytesArray.GetLength(1); index++)
// third dimension
for (int index = 0; index < bytesArray.GetLength(2); index++)
Upvotes: 1
Reputation: 50215
You're using two different ForEach
'es.
Array.ForEach in the byte[,,]
example (though you're using it incorrectly) and List.ForEach in the List<...>
example.
Upvotes: 2