Nikhil Agrawal
Nikhil Agrawal

Reputation: 48568

Enumerable.Repeat has some memory issues?

I initialized an Array as

Double[][] myarr = Enumerable.Repeat(new double[12], 13).ToArray();

Then in a loop i am incrementing values like

myarr[0][0]++; 

This causes all values like myarr[1][0], myarr[2][0], myarr[3][0] ..... myarr[12][0] to increment by one.

This problem is not occurring when using a for loop (0-12) i am initializing like

myarr[i] = new double[12];

Why is this so?

Upvotes: 1

Views: 1029

Answers (6)

Pavel Krymets
Pavel Krymets

Reputation: 6293

With new double[12] you are creating reference to array of doubles, and then you repeate the reference 12 times, so myarr[0..n] will have reference to one memory region.

You can use the folowing method to resolve thw issue

static T[][] CreateArray<T>(int rows, int cols)
{
    T[][] array = new T[rows][];
    for (int i = 0; i < array.GetLength(0); i++)
        array[i] = new T[cols];

    return array;
}

Or with custom Repeat method which calls action every step:

public static IEnumerable<TResult> RepeatAction<TResult>(Action<TResult> elementAction, int count)
{
    for (int i = 0; i < count; i++)
    {
        yield return elementAction();
    }
    yield break;
}
usage
RepeatAction(()=>new double[12], 12);

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500785

Other answers have explained the problem. The solution is to create a new array on each iteration, e.g.

double[][] myarr = Enumerable.Range(0, 13)
                             .Select(ignored => new double[12])
                             .ToArray();

Upvotes: 5

VinayC
VinayC

Reputation: 49195

This is expected behavior - array is a referebce type. You are creating a jagged array i.e. array of arrays. All elements of your outer array references the same inside array i.e the first argument of Repeat call, so changes in the inside array will be reflected at on indices (because all indices refer to the same array).

Upvotes: 2

sll
sll

Reputation: 62504

Repeat() basically just capture and yields the same element multiple times, so you got multiple references to the same object instance in the memory.

This is how Repeat() is implemented:

private static IEnumerable<TResult> RepeatIterator<TResult>(TResult element, int count)
{
    for (int i = 0; i < count; i++)
    {
        yield return element;
    }
    yield break;
}

Upvotes: 1

Ben Cottrell
Ben Cottrell

Reputation: 6120

It's because new double[12] creates a single array object in memory - Enumerable.Repeat is simply providing you with multiple references to that array.

Upvotes: 2

Lucero
Lucero

Reputation: 60190

Arrays are references. In the Repeat call you create one array and assign its reference 12 times. In your loop however you create 12 distinct arrays.

Upvotes: 1

Related Questions