for array c# .net

array - foreach var c#



foreach con Lista genérica, detectando la primera iteración al usar el tipo de valor (8)

Bueno, podrías codificarlo usando iteración explícita:

using(var iter = ints.GetEnumerator()) { if(iter.MoveNext()) { // do "first" with iter.Current while(iter.MoveNext()) { // do something with the rest of the data with iter.Current } } }

La opción de bandera bool (con foreach ) es probablemente más fácil ... ¡eso es lo que (casi) siempre hago!

Otra opción sería LINQ:

if(ints.Any()) { var first = ints.First(); // do something with first } foreach(var item in ints.Skip(1)) { // do something with the rest of them }

La desventaja de lo anterior es que trata de mirar la lista 3 veces ... ya que sabemos que es una lista, eso está bien, pero si todo lo que teníamos fuera un IEnumerable<T> , sería sensato repetirlo una vez (ya que la fuente podría no ser regrabable).

Cuando foreach en una lista genérica, a menudo quiero hacer algo diferente para el primer elemento de la lista:

List<object> objs = new List<object> { new Object(), new Object(), new Object(), new Object() }; foreach (object o in objs) { if (o == objs.First()) { System.Diagnostics.Debug.WriteLine("First object - do something special"); } else { System.Diagnostics.Debug.WriteLine("object Do something else"); } }

Esto dará como resultado:

First object - do something special object Do something else object Do something else object Do something else

Esto está todo bien y elegante.

Sin embargo, si mi lista genérica es de un tipo de valor, este enfoque fallará.

List<int> ints = new List<int> { 0, 0, 0, 0 }; foreach (int i in ints) { if (i == ints.First()) { System.Diagnostics.Debug.WriteLine("First int - do something special"); } else { System.Diagnostics.Debug.WriteLine("int Do something else"); } }

Esto dará como resultado:

First int - do something special First int - do something special First int - do something special First int - do something special

Ahora sé que podría recodificar esto para agregar una variable de bandera boolean o tradicional for bucle, pero me pregunto si hay alguna forma de averiguar si un bucle foreach está en la primera iteración de su bucle.


Como ya está utilizando LINQ, puede hacer esto:

var list = new List<Int32>(); // do something with list.First(); foreach (var item in list.Skip(1)) { // do other stuff }


El problema que tiene es que la igualdad para los tipos de valores se basa en el valor real, no en la referencia en sí. Específicamente, en su ejemplo, su lista es todos ceros, por lo que se pregunta si currentItem == firstItem, y dado que ambos son cero, esto siempre es cierto. Para este tipo de cosas, siempre terminé usando una bandera booleana.


En lugar de if (i == ints.First()) , ¿funciona si usa if (i.Equals(ints.First()) ?


Hace un tiempo escribí SmartEnumerable (parte de MiscUtil) que le permite saber si el elemento actual es el primero o el último, así como su índice. Eso puede ayudarlo ... es parte de MiscUtil, que es de código abierto; puede tomar solo SmartEnumerable bajo la misma licencia, por supuesto.

Código de muestra (c''n''p de la página web):

using System; using System.Collections.Generic; using MiscUtil.Collections; class Example { static void Main(string[] args) { List<string> list = new List<string>(); list.Add("a"); list.Add("b"); list.Add("c"); list.Add("d"); list.Add("e"); foreach (SmartEnumerable<string>.Entry entry in new SmartEnumerable<string>(list)) { Console.WriteLine ("{0,-7} {1} ({2}) {3}", entry.IsLast ? "Last ->" : "", entry.Value, entry.Index, entry.IsFirst ? "<- First" : ""); } } }

EDITAR: tenga en cuenta que si bien funciona con tipos de referencia con referencias distintas, seguirá fallando si le da una lista donde aparezca la primera referencia en cualquier otro lugar de la lista.


Si realmente no desea usar un booleano, podría hacer algo como:

List<int> ints = new List<int> { 0, 0, 0, 0 }; System.Diagnostics.Debug.WriteLine("First int - do something special" + ints.FirstOrDefault().ToString()); foreach (int i in ints.Skip(1)) { { System.Diagnostics.Debug.WriteLine("int Do something else"); } }

Pero eso parece un poco ... extraño :)


foreach(int i in ints.Take(1)) { //do first thing } foreach(int i in ints.Skip(1)) { //do other things }


Editando camino desde otra respuesta:

IList<object> objs = new List<object> { new Object(), new Object(), new Object(), new Object() }; // to access first element: objs[0] // to access last element: objs[objs.Count - 1] System.Diagnostics.Debug.WriteLine("First object - do something special"); foreach (object o in objs.Skip(1)) { System.Diagnostics.Debug.WriteLine("object Do something else"); }

Enlace de referencia sobre:

Uso del método Skip : Enumerable.Skip (IEnumerable, Int32)

Utilizando IList<T> : List o IList