Инициализация массива с конструктором по умолчанию
-
27-10-2019 - |
Вопрос
public class Sample
{
static int count = 0;
public int abc;
public Sample()
{
abc = ++Sample.count;
}
}
Я хочу создать массив вышеупомянутого класса и хочу, чтобы каждый элемент в массиве был инициализирован, вызывая конструктор по умолчанию, чтобы каждый элемент мог иметь разные abc
. Так я сделал это:
Sample[] samples = new Sample[100];
Но это не делает то, что, я думаю, это должно сделать. Похоже, что конструктор по умолчанию не вызывается. Как вызвать конструктор по умолчанию при создании массива?
Я также хотел бы знать, что делает вышеприведенное утверждение?
Решение
Вы не можете, в основном. Когда вы создаете массив, он всегда изначально заполняется значением по умолчанию для типа - который для класса всегда является нулевой ссылкой. За int
это 0, для bool
это ложь и т. д.
(Если вы используете инициализатор массива, это создаст «пустой» массив и тогда Заполните его значениями, которые вы указали, конечно.)
Существуют различные способы заполнения массива, назвав конструктор - я хотел бы вероятно Просто используйте Foreach Loop сам. Использование LINQ с перечисленным.
Конечно, вы всегда могли бы записывать Ваш собственный метод населения, даже в качестве метода расширения:
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>
, передавая индекс поставщику - Метод неэклейки, который создает массив а также Заполняет это
Другие советы
Ваш код создает только множество, но ни один из его предметов. В основном вам нужно Хранить экземпляры из Sample
в этот массив.
Проще говоря, без какого -либо причудливого Linq и т. Д.:
Sample[] samples = new Sample[100];
for (int i = 0; i < samples.Length; i++) samples[i] = new Sample();
Также обратите внимание, что ваше решение нет потокобезопасность.
Нет возможности сделать это автоматически; Инициализация массива по сути является «протиранием этого блока памяти до 0s». Вы должны были бы сделать что -то вроде:
var arr = new SomeType[size];
for(int i = 0 ; i < size ; i++) arr[i] = new SomeType();
На этом этапе у вас есть пустой массив размера 100, если вы хотите заполнить его предметами, вам придется сделать что -то вроде:
for(int i=0; i<samples.Length; i++) {
samples[i] = new Sample();
}
Проблема в том, что, заявив об этом массиве, вы никогда не выделяли пространство для каждого объекта. Вы просто выделили пространство для 100 объектов образца типа. Вам придется позвонить конструктору на каждого.
Уточнить:
Food[] foods = Food[100];
for (int k = 0; k < foods.length; k++) {
foods[k] = new Food();
}
Интересная работа вокруг может быть заводской функцией. Подумайте о том, чтобы прикрепить это к своему образцу классу.
public static Sample[] getInstances(int aNumber) {
Sample[] sample = Sample[aNumber];
for (int k = 0; k < sample.length; k++) {
sample[k] = new Sample();
}
return sample;
}
Укрывает пятна, немного - это полезное для вас полезное функцию.
Вот еще одна одна строка, которая не требует никакого метода расширения:
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();