Инициализация массива с конструктором по умолчанию - PullRequest
18 голосов
/ 30 января 2011
public class Sample
{
     static int count = 0;
     public int abc;
     public Sample()
     {
        abc = ++Sample.count;
     }
}

Я хочу создать массив вышеупомянутого класса и хочу, чтобы каждый элемент в массиве был инициализирован путем вызова конструктора по умолчанию, чтобы каждый элемент мог иметь разные abc. Так что я сделал это:

Sample[] samples = new Sample[100];

Но это не делает то, что я думаю, что должно сделать.Кажется, таким образом конструктор по умолчанию не вызывается.Как вызвать конструктор по умолчанию при создании массива?

Я также хотел бы знать, что делает приведенный выше оператор?

Ответы [ 6 ]

42 голосов
/ 30 января 2011

Вы не можете, в основном. Когда вы создаете массив, он всегда изначально заполняется значением по умолчанию для типа, которое для класса всегда является пустой ссылкой. Для int это 0, для bool это ложь и т. Д.

(Если вы используете инициализатор массива, который создаст «пустой» массив и , то заполнит его, конечно, указанными вами значениями.)

Существуют различные способы заполнения массива путем вызова конструктора - я бы , вероятно, просто использовал бы цикл foreach самостоятельно. Использование LINQ с Enumerable.Range / Repeat выглядит немного вынужденным.

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

public static T[] Populate<T>(this T[] array, Func<T> provider)
{
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = provider();
    }
    return array;
}

Тогда вы можете использовать:

Sample[] samples = new Sample[100].Populate(() => new Sample());

Что мне нравится в этом решении:

  • Это все еще одно выражение, которое может быть полезно в различных сценариях
  • Он не вводит понятия, которые вам на самом деле не нужны (например, повторение одного значения или создание диапазона)

Конечно, вы можете добавить больше опций:

  • Перегрузка, которая принимает Func<int, T> вместо Func<T>, передавая индекс поставщику
  • Метод без расширения, который создает массив и заполняет его
8 голосов
/ 30 января 2011

Ваш код создает только массив , но ни один из его элементов. По сути, вам нужно хранить экземпляры из Sample в этом массиве.

Проще говоря, без всяких причудливых LINQ и т. Д.: * 10101

Sample[] samples = new Sample[100];
for (int i = 0; i < samples.Length; i++) samples[i] = new Sample();

Обратите внимание, что ваше решение не поточно-ориентированное.

4 голосов
/ 30 января 2011

Нет способа сделать это автоматически;инициализация массива по сути "стереть этот блок памяти с нуля".Вы должны сделать что-то вроде:

var arr = new SomeType[size];
for(int i = 0 ; i < size ; i++) arr[i] = new SomeType();
2 голосов
/ 30 января 2011

На данный момент у вас есть пустой массив размером 100, если вы хотите заполнить его элементами, то вам придется сделать что-то вроде:

for(int i=0; i<samples.Length; i++) {
   samples[i] = new Sample();
}
2 голосов
/ 30 января 2011

Проблема в том, что, объявляя этот массив, вы никогда не выделяете место для каждого объекта.Вы просто выделили пространство для 100 объектов типа Sample.Вам придется вызывать конструктор для каждого из вас.

Для уточнения:

Food[] foods = Food[100];
for (int k = 0; k < foods.length; k++) {
   foods[k] = new Food();
}

Интересным обходным решением может быть фабричная функция.Подумайте о том, чтобы присоединить это к вашему классу Sample.

public static Sample[] getInstances(int aNumber) {
    Sample[] sample = Sample[aNumber];
    for (int k = 0; k < sample.length; k++) {
       sample[k] = new Sample();
    }

    return sample;
}

Немного скрывает недостатки - при условии, что это полезная функция для вас.

1 голос
/ 10 июля 2014

Вот еще одна строка, которая не требует какого-либо метода расширения:

Sample[] array = Enumerable.Range(0, 100).Select(i => new Sample()).ToArray();

Еще один приятный вариант - предложение Скотта до ответ Джона :

public static T[] Populate<T>(this T[] array) 
    where T : new()
{
    for (int i = 0; i < array.Length; i++)
        array[i] = new T();
    return array;
}

Так что вы можете сделать:

Sample[] array = new Sample[100].Populate();
...