2011-01-29 3 views
15
public class Sample 
{ 
    static int count = 0; 
    public int abc; 
    public Sample() 
    { 
     abc = ++Sample.count; 
    } 
} 

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

Sample[] samples = new Sample[100]; 

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

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

+0

почему бы вам не просто использовать индекс массива, его уникальный и авто инкрементальный в соответствии с вашим кодом –

+2

На стороне записки - этот код не поточно-; вы должны использовать 'id = Interlocked.Increment (ref count)' и начать с 'static int count = 1' (поскольку' Interlocked.Increment' возвращает значение * old *). –

+0

ну в коде выше вы только что объявили массив размером 100, в нем нет элементов. – Victor

ответ

38

Вы не можете, в основном. Когда вы создаете массив, он всегда изначально заполняется значением по умолчанию для типа, которое для класса всегда является пустой ссылкой. Для 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>, передавая индекс к провайдеру
  • способ не-расширение, которое создает массив и заполняющий его
+2

Мне понравилось это решение больше всего. :-) Многоразовый метод. :-) – Nawaz

+2

Другая полезная перегрузка - это замена ', Func провайдер)' with '), где T: new()', и вам вовсе не нужно передавать делегат, если вы просто используете конструктор по умолчанию (вы также необходимо будет заменить 'provider()' на 'new T()'). –

4

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

var arr = new SomeType[size]; 
for(int i = 0 ; i < size ; i++) arr[i] = new SomeType(); 
8

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

Выражаясь просто, без каких-либо фантазии LINQ и т.д .:

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

Обратите внимание, что Ваше решение не потокобезопасной.

2

Проблема в том, что, объявив этот массив, вы никогда не выделяли место для каждого объекта. Вы просто выделили место для 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; 
} 

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

+0

Так что это минимальный код, который я должен написать? – Nawaz

+0

Я отредактировал его с решением, которое вам может понравиться. Короткий ответ - да. :/ – Mike

+0

Вы создаете массив 'Food', но возвращаемый тип' Sample [] ': P – Nawaz

2

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

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

Вот еще один лайнер, который Безразлично» т требует каких-либо метод расширения:

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

Другой хороший вариант Scott's suggestionJon's 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(); 
Смежные вопросы