I want write extension method for fill multidimensional rectangular array. I know how to do it for the array with a fixed number of measurements:
public static void Fill<T>(this T[] source, T value)
{
    for (int i = 0; i < source.Length; i++)
        source[i] = value;
}
public static void Fill<T>(this T[,] source, T value)
{
    for (int i = 0; i < source.GetLength(0); i++)
        for (int j = 0; j < source.GetLength(1); j++)
            source[i, j] = value;
}
public static void Fill<T>(this T[,,] source, T value)
{
    for (int i = 0; i < source.GetLength(0); i++)
        for (int j = 0; j < source.GetLength(1); j++)
            for (int k = 0; k < source.GetLength(2); k++)
                source[i, j, k] = value;
}
Can I write one fill-method for all multidimensional rectangular array?
You can change the fixed dimension parameter to an Array parameter so you can put the extension on any Array. Then I used recursion to iterate through each position of the array.
public static void Fill<T>(this Array source, T value)
{
    Fill(0, source, new long[source.Rank], value);
}
static void Fill<T>(int dimension, Array array, long[] indexes, T value)
{
    var lowerBound = array.GetLowerBound(dimension);
    var upperBound = array.GetUpperBound(dimension);
    for (int i = lowerBound; i <= upperBound; i++)
    {
        indexes[dimension] = i;
        if (dimension < array.Rank - 1)
        {
            Fill(dimension + 1, array, indexes, value);
        }
        else
        {
            array.SetValue(value, indexes);
        }
    }
}
                        Here's a solution that does not use recursion (and is less complex):
   public static void FillFlex<T>(this Array source, T value)
    {
        bool complete = false;
        int[] indices = new int[source.Rank];
        int index = source.GetLowerBound(0);
        int totalElements = 1;
        for (int i = 0; i < source.Rank; i++)
        {
            indices[i] = source.GetLowerBound(i);
            totalElements *= source.GetLength(i);
        }
        indices[indices.Length - 1]--;
        complete = totalElements == 0;
        while (!complete)
        {
            index++;
            int rank = source.Rank;
            indices[rank - 1]++;
            for (int i = rank - 1; i >= 0; i--)
            {
                if (indices[i] > source.GetUpperBound(i))
                {
                    if (i == 0)
                    {
                        complete = true;
                        return;
                    }
                    for (int j = i; j < rank; j++)
                    {
                        indices[j] = source.GetLowerBound(j);
                    }
                    indices[i - 1]++;
                }
            }
            source.SetValue(value, indices);
        }
    }
This is modeled from the System.Array.ArrayEnumerator. This implementation should have a similar level of correctness as ArrayEnumerator and (based on a few spot checks) appears to function fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With