Jonathan Wood
Jonathan Wood

Reputation: 67213

Implementing LINQ-Style Extension Method on Two-Dimensional Array

I have some code that works with a two-dimensional grid (array) and I ended up with a lot of routines that loop through each item in the grid.

But I thought it would be nice if I could do this LINQ-style using extension methods.

Here's what I tried so far:

private static void ForEach(this MyType[,] grid, Action<MyType> action)
{
    for (int row = 0; row < grid.GetUpperBound(0); row++)
        for (int col = 0; col < grid.GetUpperBound(1); col++)
            action(grid[row, col]);
}

1. Intellisense doesn't seem to recognize this extension method on an object of type MyType[3,3]. Am I missing something about writing an extension method for a two-dimensional array?

2. What is the recommended way to implement such a pattern that allows me to conditionally set the grid value? Using the code above, setting the passed value would not affect the original array.

EDIT:

Okay, after originally implementing this extension method within the same class it was called from, I stupidly left it declared as private when I moved it to an external class. I guess it won't work as a private method in the same class and it obviously won't work as a private method in an external class.

Would still love to see an answer to number 2 though.

Upvotes: 2

Views: 1135

Answers (1)

D Stanley
D Stanley

Reputation: 152566

For your second question, an Action will not work because it does not return a value, so it could not directly update the array. What you may want is a Func<MyType,MyType> that will take in the original value, do some processing, and return a new value that your ForEach will then plop back into the array. If you need to know the row and column then make it a Func<MyType, int, int>.

As a side note, I would not call it ForEach since you are modifying the underlying collection (which ForEach cannot do in a normal collection). I would call it UpdateAll or something like that.

So you end up with something like:

public static void UpdateAll(this MyType[,] grid, Func<MyType,MyType> action)
{
    for (int row = grid.GetLowerBound(0); row <= grid.GetUpperBound(0); row++)
        for (int col = grid.GetLowerBound(1); col <= grid.GetUpperBound(1); col++)
            grid[row, col] = action(grid[row, col]);
}

Note that it uses GetLowerBound and uses <= instead of < on the upper bound check.

Upvotes: 2

Related Questions