c # usando Array.ForEach Acción predicado con matriz de tipo valor o cadena
Pregunta
Estoy en lo correcto al pensar el siguiente fragmento no funciona (los elementos de matriz no se modifican) ya es la matriz de número entero que es el tipo de valor.
class Program
{
public static void Main()
{
int[] ints = new int[] { 1,2 };
Array.ForEach(ints, new Action<int>(AddTen));
// ints is not modified
}
static void AddTen(int i)
{
i+=10;
}
}
Lo mismo ocurriría si el ejemplo utiliza una matriz de cadena, presumiblemente debido a que la cadena es inmutable.
La pregunta que tengo es: -
¿Hay una manera de evitar esto? No puedo cambiar la firma del método de devolución de llamada - por ejemplo mediante la adición de la palabra clave ref y no quiero envolver el tipo de valor con una clase - que trabajaría ...
(Por supuesto, yo podría simplemente escribir un viejo bucle foreach moda para hacer esto!)
Solución
Usted es simplemente cambiando la variable local - no es el elemento de la lista. Para ello, desea ConvertAll
, lo que crea una nueva lista / matriz:
int[] ints = new int[] { 1,2 };
int[] newArr = Array.ConvertAll<int,int>(ints, AddTen);
por:
static int AddTen(int i)
{
return i+10;
}
Esto también se puede escribir con un método anónimo:
int[] newArr = Array.ConvertAll<int,int>(ints,
delegate (int i) { return i+ 10;});
O en C # 3.0 como lambda:
int[] newArr = Array.ConvertAll(ints, i=>i+10);
Aparte de eso ... un bucle for
:
for(int i = 0 ; i < arr.Length ; i++) {
arr[i] = AddTen(arr[i]); // or more directly...
}
Pero de una manera u otra, van a tener que conseguir un valor a cabo de su método. A menos que cambie la firma, no se puede.
Otros consejos
El método Array.ForEach () no le permite modificar prácticamente a sus miembros. Se puede modificar mediante el uso de LINQ como este
ints = ints.Select(x => x +10 ).ToArray();
foreach es la única manera, los tipos de valor en las matrices y listas siempre se copian y su modificación por lo tanto no va a funcionar, a menos que se almacena el valor modificado espalda. El método AddTen no está haciendo eso, se modifica su propia copia.
En primer lugar, por lo general es peligroso para modificar la colección que estés foreach
ing terminado. La mayoría de las colecciones mantienen una "etiqueta de versión" interno para realizar un seguimiento de los cambios, por lo que se empadronador una excepción cuando se attemt para iterar sobre la colección modificada.
En cuanto a su pregunta, no hay manera de que pueda hacer eso con los tipos de valores y Array.ForEach
. Utilice foreach
o Convert
a hacer lo que quiera.