1
\$\begingroup\$

I am working with System.Array and I found that the input parameter of ForEach method public static void ForEach<T>(T[] array, Action<T> action); is specified on one dimensional array case. I am trying to generalize this to multidimensional array.

The experimental implementation

Here's the experimental implementation of generalized ForEach method.

class ArrayHelpers
{
    public static void ForEach<T>(Array array, in Action<T> action)
        where T : unmanaged
    {
        if (ReferenceEquals(array, null))
        {
            throw new ArgumentNullException(nameof(array));
        }

        if (ReferenceEquals(action, null))
        {
            throw new ArgumentNullException(nameof(action));
        }

        foreach (T item in array)
        {
            action.Invoke(item);
        }
        return;
    }
}

Test cases

The Test cases for one dimensional case, two dimensional case and three dimensional case are as below.

//    One dimensional case
Console.WriteLine("One dimensional case");
int[] test = new int[] { 1, 2, 3, 4 };
ArrayHelpers.ForEach<int>(test, ShowSquares);

//    two dimensional case
Console.WriteLine("Two dimensional case");
int[,] test2 = { { 0, 1 }, { 2, 3 } };
ArrayHelpers.ForEach<int>(test2, ShowSquares);

//    three dimensional case
Console.WriteLine("Three dimensional case");
int[,,] test3 = { { { 0, 1 }, { 2, 3 } }, { { 0, 1 }, { 2, 3 } } };
ArrayHelpers.ForEach<int>(test3, ShowSquares);

/// <summary>
/// Reference: https://docs.microsoft.com/en-us/dotnet/api/system.array.foreach?view=net-5.0
/// </summary>
/// <param name="val">The input value for displaying and calculating square result</param>
private static void ShowSquares(int val)
{
    Console.WriteLine("{0:d} squared = {1:d}", val, val * val);
}

The output of the above tests:

One dimensional case
1 squared = 1
2 squared = 4
3 squared = 9
4 squared = 16
Two dimensional case
0 squared = 0
1 squared = 1
2 squared = 4
3 squared = 9
Three dimensional case
0 squared = 0
1 squared = 1
2 squared = 4
3 squared = 9
0 squared = 0
1 squared = 1
2 squared = 4
3 squared = 9

I am wondering the things about the potential drawback or risks of this implementation.

All suggestions are welcome.

\$\endgroup\$
1
\$\begingroup\$

The solution is fine as it easy as it could be but there's a better way to make the access to it - extension method.

public static class ArrayHelpers
{
    public static void ForEach<T>(this Array array, in Action<T> action)
    {
        if (ReferenceEquals(array, null))
        {
            throw new ArgumentNullException(nameof(array));
        }

        if (ReferenceEquals(action, null))
        {
            throw new ArgumentNullException(nameof(action));
        }

        foreach (T item in array)
        {
            action.Invoke(item);
        }
        return;
    }
}

Then the test cases can look like this

Console.WriteLine("One dimensional case");
int[] test = new int[] { 1, 2, 3, 4 };
test.ForEach<int>(ShowSquares);

Console.WriteLine("Two dimensional case");
int[,] test2 = { { 0, 1 }, { 2, 3 } };
test2.ForEach<int>(ShowSquares);

Console.WriteLine("Three dimensional case");
int[,,] test3 = { { { 0, 1 }, { 2, 3 } }, { { 0, 1 }, { 2, 3 } } };
test3.ForEach<int>(ShowSquares);
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Good call on the extensions implementation. I would suggest to rename the class to ArrayExtensions to clearly indicate the fact that is an extensions class. \$\endgroup\$
    – Abbas
    Mar 4 '21 at 6:43
  • \$\begingroup\$ @Abbas agree. But as for me ArrayHelpers, ArrayTools, ArrayUtilities are fine as ArrayExtensions. \$\endgroup\$
    – aepot
    Mar 4 '21 at 7:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.