2012-04-09 5 views
1

Я инициализируется массив, какEnumerable.Repeat имеет некоторые проблемы с памятью?

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

Затем в цикле я приращением значений, как

Это вызывает все значения, такие как myarr [1] [0], myarr [2] [0] , myarr [3] [0] ..... myarr [12] [0] для увеличения на единицу.

Эта проблема не происходит при использовании для цикла (0-12) я инициализирующий как

myarr[i] = new double[12]; 

Почему это так?

ответ

5

Другие ответы объяснили проблему. Решение состоит в том, чтобы создать новый массив на каждой итерации, например.

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

Массивы - это ссылки. В вызове Repeat вы создаете один массив и назначаете его ссылку 12 раз. Однако в вашем цикле вы создаете 12 различных массивов.

2

С new double[12] вы создаете ссылку на массив удваивается, а затем вы repeate в эталонные 12 раз, так myarr [0..n] будет иметь ссылку на одну область памяти.

Вы можете использовать метод folowing для решения 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; 
} 

или с пользовательским методом Repeat, который вызывает действие на каждый шаг:

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); 
2

Это потому, что new double[12] создает один объект массива в памяти - Enumerable.Repeat просто предоставляет вам несколько ссылок на этот массив.

+0

Каково использование такого объекта (несколько ссылок на этот массив)? Это приведет к неправильным значениям массива. –

1

Repeat() в основном просто захватывает и дает один и тот же элемент несколько раз, поэтому вы получили несколько ссылок на один и тот же экземпляр объекта в памяти.

Это как Repeat() реализуется:

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

Это ожидаемое поведение - массив типа referebce. Вы создаете зубчатый массив, то есть массив массивов. Все элементы вашего внешнего массива ссылаются на один и тот же внутренний массив. Первый аргумент вызывает Repeat, поэтому изменения внутри массива будут отражаться по индексам (поскольку все индексы относятся к одному и тому же массиву).

+0

Каково использование такого объекта (несколько ссылок на этот массив)? Это приведет к неправильным значениям массива. –

Смежные вопросы