Инициализация массива с помощью конструктора по умолчанию
public class Sample
{
static int count = 0;
public int abc;
public Sample()
{
abc = ++Sample.count;
}
}
Я хочу создать массив выше класса и хочу, чтобы каждый элемент в массиве был инициализирован путем вызова конструктора по умолчанию, так что каждый элемент может иметь разные abc
. Так я сделал это:
Sample[] samples = new Sample[100];
Но это не делает то, что я думаю, что он должен делать. Кажется, что конструктор по умолчанию не вызван. Как вызвать конструктор по умолчанию при создании массива?
Я также хотел бы знать, что делает вышеуказанный оператор?
Ответы
Ответ 1
Вы не можете, в принципе. Когда вы создаете массив, он всегда изначально заполняется значением по умолчанию для типа, которое для класса всегда является пустой ссылкой. Для int
это 0, для bool
- false и т.д.
(Если вы используете инициализатор массива, это создаст "пустой" массив, а затем, конечно, заполнит его указанными вами значениями.)
Существуют различные способы заполнения массива путем вызова конструктора - я бы, вероятно, просто использовал цикл 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>
, передавая индекс провайдеру
- Метод без расширения, который создает массив и заполняет его
Ответ 2
Ваш код создает только массив, но ни один из его элементов. В принципе, вам нужно хранить экземпляры Sample
в этом массиве.
Проще говоря, без каких-либо причудливых LINQ и т.д.:
Sample[] samples = new Sample[100];
for (int i = 0; i < samples.Length; i++) samples[i] = new Sample();
Обратите внимание, что ваше решение не потокобезопасно.
Ответ 3
Нет никакого способа сделать это автоматически; инициализация массива, по сути, "уничтожает этот блок памяти до 0s". Вам нужно будет сделать что-то вроде:
var arr = new SomeType[size];
for(int i = 0 ; i < size ; i++) arr[i] = new SomeType();
Ответ 4
Проблема заключается в том, что, объявив этот массив, вы никогда не выделяли место для каждого объекта. Вы просто выделили место для 100 объектов типа Sample. Вам нужно будет вызвать конструктор для каждого из вас.
Разработать:
Food[] foods = Food[100];
for (int k = 0; k < foods.length; k++) {
foods[k] = new Food();
}
Интересной работой может быть функция factory. Подумайте о присоединении этого к классу 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;
}
Скрывает дефект, немного - предоставляя вам полезную функцию.
Ответ 5
В этот момент у вас есть пустой массив размером 100, если вы хотите заполнить его элементами, тогда вам нужно будет сделать что-то вроде:
for(int i=0; i<samples.Length; i++) {
samples[i] = new Sample();
}
Ответ 6
Вот еще один однострочный, который не требует какого-либо метода расширения:
Sample[] array = Enumerable.Range(0, 100).Select(i => new Sample()).ToArray();
Другим приятным вариантом является предложение Скотта на Jon answer:
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();