Array de inicialización con constructor por defecto

public class Sample { static int count = 0; public int abc; public Sample() { abc = ++Sample.count; } } 

Quiero crear una matriz de la clase anterior, y quiero que cada elemento en la matriz se inicialice invocando el constructor predeterminado, para que cada elemento pueda tener diferentes abc . Así que hice esto:

 Sample[] samples = new Sample[100]; 

Pero esto no hace lo que creo que debería hacer. Parece que de esta manera no se llama al constructor predeterminado. ¿Cómo invocar el constructor predeterminado al crear una matriz?

También me gustaría saber qué hace la afirmación anterior.

No puedes, básicamente. Cuando se crea una matriz, siempre se rellena inicialmente con el valor predeterminado para el tipo, que para una clase es siempre una referencia nula. Para int es 0, para bool es falso, etc.

(Si usa un inicializador de matriz, eso creará la matriz “vacía” y luego la rellenará con los valores que ha especificado, por supuesto).

Hay varias maneras de poblar la matriz llamando al constructor; probablemente usaré un bucle foreach por mi cuenta. Usar LINQ con Enumerable.Range / Repeat se siente un poco forzado.

Por supuesto, siempre puedes escribir tu propio método de población, incluso como método de extensión:

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

Entonces podrías usar:

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

Lo que me gusta de esta solución:

  • Todavía es una expresión única, que puede ser útil en varios escenarios
  • No presenta conceptos que realmente no desea (como repetir un solo valor o crear un rango)

Por supuesto, podrías agregar más opciones:

  • Una sobrecarga que toma un Func lugar de un Func , pasando el índice al proveedor
  • Un método sin extensión que crea la matriz y la rellena

Tu código crea solo la matriz , pero ninguno de sus elementos. Básicamente, debe almacenar instancias de Sample en esta matriz.

Para decirlo de manera simple, sin ningún LINQ de lujo, etc.

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

Tenga en cuenta que su solución no es segura para subprocesos.

No hay forma de hacer esto automáticamente; la inicialización del array es esencialmente “borrar este bloque de memoria a 0s”. Deberías hacer algo como:

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

En este punto, tiene una matriz vacía de tamaño 100, si desea llenarla con elementos, entonces tendría que hacer algo como:

 for(int i=0; i 

El problema es que al declarar esa matriz, nunca asignó espacio para cada objeto. Simplemente asignó espacio para 100 objetos de tipo Muestra. Tendrá que llamar al constructor en cada uno usted mismo.

Elaborar:

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

Un trabajo interesante podría ser una función de fábrica. Considere adjuntar esto a su clase de muestra.

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

Oculta la imperfección, un poco, siempre que esta sea una función útil para usted.

Aquí hay otro delineador que no requiere ningún método de extensión:

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

Otra buena opción es la sugerencia de Scott a la respuesta de Jon :

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

Entonces puedes hacer:

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