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

Quiero crear una matriz de clase por encima, y ​​desea que cada elemento de la matriz a ser inicializado mediante la invocación del constructor por defecto, de manera que cada elemento puede tener diferentes abc .Así lo hice :inicialización de la matriz con el constructor por defecto

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 declaración anterior?

+0

¿Por qué no sólo tiene que utilizar el índice de matriz, su incremento único y automático como por su código –

+2

En una nota lateral - que el código no es seguro para subprocesos; debería usar 'id = Interlocked.Increment (ref count)' en su lugar, y comenzar con 'static int count = 1' (ya que' Interlocked.Increment' devuelve el valor * old *). –

+0

bien en el código anterior que acaba de declarar una matriz de tamaño 100, no hay elementos en ella. – Victor

Respuesta

38

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, por bool es falsa, etc.

(Si utiliza un inicializador de matriz, que va a crear la matriz de "vacío" y continuación rellenarla con los valores que ha especificado, por supuesto.)

Hay varias maneras de poblar la matriz llamando al constructor - Lo haría probablemente solo uso un bucle foreach. Usar LINQ con Enumerable.Range/Repeat se siente un poco forzado.

Por supuesto, siempre se podría escribir su propio método de la población, así como un método de extensión:

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

entonces se podría 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 introduce conceptos que en realidad no quiera (como la repetición de un solo valor o la creación de una serie)

Por supuesto, se podría añadir más opciones:

  • Una sobrecarga el cual realiza un Func<int, T> en lugar de un Func<T>, pasando el índice para el proveedor
  • un método no extensión que crea la matriz y rellena
+2

Me gustó más esta solución. :-) Método reutilizable. :-) – Nawaz

+2

Otra sobrecarga útil es reemplazar ', Func proveedor)' con ') donde T: new()' y luego no necesita pasar un delegado en absoluto si solo está usando el constructor predeterminado (también necesitará reemplazar 'provider()' con 'new T()'). –

4

No hay forma de hacerlo automáticamente; la inicialización del array es esencialmente "borrar este bloque de memoria a 0s". Usted tendría que hacer algo como:

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

Su código crea sólo el gama, pero ninguno de sus elementos. Básicamente, necesita instancias de tienda de Sampleen esta matriz.

Para decirlo simple, sin ningún tipo de fantasía LINQ, etc .:

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

Tenga en cuenta también que su solución es no flujos seguros.

2

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 alrededor podría ser una función de la 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.

+0

¿Entonces ese es el código mínimo que debo escribir? – Nawaz

+0

Lo edité con una solución que te podría gustar. La respuesta corta es sí, sin embargo. :/ – Mike

+0

Está creando una matriz de 'Comida' pero el tipo de devolución es' Muestra [] ': P – Nawaz

2

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

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

Esta es otra de una sola línea que doesn' t requiere ningún método de extensión:

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

Otra buena opción es Scott's suggestion-Jon'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; 
} 

lo que puede hacer:

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