2008-09-25 25 views
31

¿Cuál es la forma más hábil de inicializar una matriz de tamaño dinámico en C# que conozca?C# Inicialización de matriz - con valor no predeterminado

Esto es lo mejor que podía llegar a

private bool[] GetPageNumbersToLink(IPagedResult result) 
{ 
    if (result.TotalPages <= 9) 
     return new bool[result.TotalPages + 1].Select(b => true).ToArray(); 

    ... 

Respuesta

34

uso Enumerable.Repeat

Enumerable.Repeat(true, result.TotalPages + 1).ToArray() 
+1

¡Eso es simplemente resbaladizo! – Rob

+12

Creo que la nota de rendimiento de Nigel merece una mención: http://stackoverflow.com/questions/136836/c-array-initialization-with-non-default-value/1051227#1051227 – CrimsonX

+9

No puedo creer que las personas voten a favor de algo que es tan 'difusa' (en mi opinión) y costosa para una operación tan simple como llenar una matriz. 'var arr = new type [10]; for (int i = 0; i Aidiakapi

0

no probado, pero podría usted acaba de hacer esto?

return result.Select(p => true).ToArray(); 

Omitiendo el mensaje "new bool []" part?

+1

sólo si IPagedResult: IEnumerable

5

De hecho, me sugieren lo siguiente:

return Enumerable.Range(0, count).Select(x => true).ToArray(); 

De esta manera sólo asignar una matriz. Se trata esencialmente de una manera más concisa de expresar:

var array = new bool[count]; 

for(var i = 0; i < count; i++) { 
    array[i] = true; 
} 

return array; 
+1

O incluso nueva bool [recuento ] .Seleccione (x => verdadero) .ToArray() – BjartN

+2

Eso aún asignaría dos matrices. –

13

EDIT: como un comentarista señaló, mi implementación original no funcionó. Esta versión funciona, pero no está muy bien, ya que se basa en un ciclo for.

Si usted está dispuesto a crear un método de extensión, puede probar con este

public static T[] SetAllValues<T>(this T[] array, T value) where T : struct 
{ 
    for (int i = 0; i < array.Length; i++) 
     array[i] = value; 

    return array; 
} 

e invocarla como esto

bool[] tenTrueBoolsInAnArray = new bool[10].SetAllValues(true); 

Como alternativa, si estás contento con teniendo una clase dando vueltas, podrías probar algo como esto

public static class ArrayOf<T> 
{ 
    public static T[] Create(int size, T initialValue) 
    { 
     T[] array = (T[])Array.CreateInstance(typeof(T), size); 
     for (int i = 0; i < array.Length; i++) 
      array[i] = initialValue; 
     return array; 
    } 
} 

que se puede invocar como

bool[] tenTrueBoolsInAnArray = ArrayOf<bool>.Create(10, true); 

No estoy seguro de que yo prefiero, aunque me lurv métodos de extensión de los lotes y lotes en general.

+0

No creo que su SetAllValues ​​funcione: en su expresión lambda, x no se pasa por referencia, por lo que asignarle un valor no cambia el valor almacenado en la matriz. –

+0

Sí, tienes toda la razón. Mencioné que no lo había compilado realmente, lo que habría mostrado ese error bastante elemental. Reemplacé el ForEach con un bucle simple y eso funciona bien, pero no es perfecto como lo exigió el interrogador. –

+1

Aparte de eso, su método de extensión tiene una firma que implica que devolverá una nueva matriz, pero modifica la matriz original y la devuelve en su lugar. Mala forma. –

70

Si por 'diestros' quiere decir más rápida, me temo que Enumerable.Repeat puede ser 20 veces más lento que un para bucle. Ver http://dotnetperls.com/initialize-array:

Initialize with for loop:    85 ms [much faster] 
Initialize with Enumerable.Repeat: 1645 ms 

lo que el uso de SetAllValues ​​Dotnetguy método().

+11

+1 para la nota de rendimiento. – AMissico

1

Muchas veces te gustaría para inicializar células diferentes con diferentes valores:

public static void Init<T>(this T[] arr, Func<int, T> factory) 
{ 
    for (int i = 0; i < arr.Length; i++) 
    { 
     arr[i] = factory(i); 
    } 
} 

O en el sabor de la fábrica:

public static T[] GenerateInitializedArray<T>(int size, Func<int, T> factory) 
{ 
    var arr = new T[size]; 
    for (int i = 0; i < arr.Length; i++) 
    { 
     arr[i] = factory(i); 
    } 
    return arr; 
} 
Cuestiones relacionadas