Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

whats up with this foreach in c#?

(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; });
like image 551
alan2here Avatar asked Oct 28 '11 15:10

alan2here


1 Answers

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.

like image 136
Joshua Rodgers Avatar answered Sep 23 '22 01:09

Joshua Rodgers