Es posible que desee elegir una respuesta aceptada diferente, ya que la que seleccionó no representa realmente la respuesta correcta.
George Stocker
Respuestas:
162
En realidad, estrictamente hablando, todo lo que necesita usar foreaches un GetEnumerator()método público que devuelva algo con un bool MoveNext()método y una ? Current {get;}propiedad. Sin embargo, el significado más común de esto es "algo que implementa IEnumerable/ IEnumerable<T>, devolviendo un IEnumerator/ IEnumerator<T>.
Por implicación, esto incluye cualquier cosa que implementa ICollection/ ICollection<T>, como por ejemplo algo como Collection<T>, List<T>, matrices ( T[]), etc. Por lo que cualquier "recopilación de datos" estándar generalmente apoyar foreach.
Como prueba del primer punto, lo siguiente funciona bien:
using System;
classFoo {
publicint Current { get; privateset; }
privateint step;
publicboolMoveNext() {
if (step >= 5) returnfalse;
Current = step++;
returntrue;
}
}
classBar {
public Foo GetEnumerator() { returnnew Foo(); }
}
staticclassProgram {
staticvoidMain() {
Bar bar = new Bar();
foreach (int item in bar) {
Console.WriteLine(item);
}
}
}
¿Como funciona?
Un bucle foreach como foreach(int i in obj) {...}equivale a:
var tmp = obj.GetEnumerator();
int i; // up to C# 4.0while(tmp.MoveNext()) {
int i; // C# 5.0
i = tmp.Current;
{...} // your code
}
Sin embargo, existen variaciones. Por ejemplo, si el enumerador (tmp) lo admite IDisposable, también se usa (similar a using).
Tenga en cuenta la diferencia en la ubicación de la declaración " int i" dentro (C # 5.0) frente a fuera (hasta C # 4.0) del bucle. Es importante si usa iun método / lambda anónimo dentro de su bloque de código. Pero esa es otra historia ;-p
+1 por profundizar. Normalmente no profundizo tanto en una pregunta que puede ser una pregunta para "principiantes", ya que parecería abrumadora para el nuevo programador.
George Stocker
Es cierto, Gortok, así que seguí con las cosas sobre listas / matrices / etc.
Marc Gravell
Sería bueno mencionar la conversión implícita en tiempo de ejecución a la variable de bucle: puede producir excepciones de incompatibilidad de tipos.
Daniel Earwicker
3
No lo olvide: cuando usa una matriz con foreach, el compilador crea un simple for-loop(puede ver esto cuando trabaja con IL).
Felix K.
1
@Marc Gravell: ¡Bien, genial! Edité la publicación para que quede más claro, al menos para mí. Después de todo, la ubicación no solo es importante en C # 5.0, siempre es importante, solo que cambió. Espero que no te moleste.
La foreachdeclaración repite un grupo de declaraciones incrustadas para cada elemento de una matriz o colección de objetos . La foreachdeclaración se usa para iterar a través de la colección para obtener la información deseada, pero no debe usarse para cambiar el contenido de la colección para evitar efectos secundarios impredecibles. (énfasis mío)
Entonces, si tiene una matriz, puede usar la instrucción foreach para iterar a través de la matriz, así:
Curiosamente, según MSDN ( msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx ), los tipos de objetos no necesitan implementar IEnumerable. Cualquier tipo que defina GetEnumerator, MoveNext, Reset y Current de la forma correcta funcionará. Extraño, ¿eh?
Sean Reilly
Ordenado. Yo no lo sabía. :-)
George Stocker
4
De acuerdo con la publicación del blog Duck Notation , se usa la escritura de pato.
Es importante tener en cuenta que "El tipo de elemento de la colección debe ser convertible al tipo de identificador". En ocasiones, esto no se puede comprobar en tiempo de compilación y puede generar una excepción en tiempo de ejecución si el tipo de instancia no se puede asignar al tipo de referencia.
Esto generará una excepción de tiempo de ejecución si hay una que no sea de Apple en la canasta de frutas, como una naranja.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)
Esto filtra de forma segura la lista solo a las manzanas usando Enumerable.OfType
List<int> numbers = new List<int>();
numbers.Add(5);
numbers.Add(15);
numbers.Add(25);
numbers.Add(35);
Console.WriteLine("You are added total number: {0}",numbers.Count);
foreach (int number in numbers)
{
Console.WriteLine("Your adding Number are: {0}", number);
}
Respuestas:
En realidad, estrictamente hablando, todo lo que necesita usar
foreach
es unGetEnumerator()
método público que devuelva algo con unbool MoveNext()
método y una? Current {get;}
propiedad. Sin embargo, el significado más común de esto es "algo que implementaIEnumerable
/IEnumerable<T>
, devolviendo unIEnumerator
/IEnumerator<T>
.Por implicación, esto incluye cualquier cosa que implementa
ICollection
/ICollection<T>
, como por ejemplo algo comoCollection<T>
,List<T>
, matrices (T[]
), etc. Por lo que cualquier "recopilación de datos" estándar generalmente apoyarforeach
.Como prueba del primer punto, lo siguiente funciona bien:
using System; class Foo { public int Current { get; private set; } private int step; public bool MoveNext() { if (step >= 5) return false; Current = step++; return true; } } class Bar { public Foo GetEnumerator() { return new Foo(); } } static class Program { static void Main() { Bar bar = new Bar(); foreach (int item in bar) { Console.WriteLine(item); } } }
¿Como funciona?
Un bucle foreach como
foreach(int i in obj) {...}
equivale a:var tmp = obj.GetEnumerator(); int i; // up to C# 4.0 while(tmp.MoveNext()) { int i; // C# 5.0 i = tmp.Current; {...} // your code }
Sin embargo, existen variaciones. Por ejemplo, si el enumerador (tmp) lo admite
IDisposable
, también se usa (similar ausing
).Tenga en cuenta la diferencia en la ubicación de la declaración "
int i
" dentro (C # 5.0) frente a fuera (hasta C # 4.0) del bucle. Es importante si usai
un método / lambda anónimo dentro de su bloque de código. Pero esa es otra historia ;-pfuente
for-loop
(puede ver esto cuando trabaja con IL).Desde MSDN :
Entonces, si tiene una matriz, puede usar la instrucción foreach para iterar a través de la matriz, así:
int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 }; foreach (int i in fibarray) { System.Console.WriteLine(i); }
También puede usarlo para iterar a través de una
List<T>
colección, así:List<string> list = new List<string>(); foreach (string item in list) { Console.WriteLine(item); }
fuente
De acuerdo con la publicación del blog Duck Notation , se usa la escritura de pato.
fuente
Aquí están los documentos: Artículo principal con matrices con objetos de colección
Es importante tener en cuenta que "El tipo de elemento de la colección debe ser convertible al tipo de identificador". En ocasiones, esto no se puede comprobar en tiempo de compilación y puede generar una excepción en tiempo de ejecución si el tipo de instancia no se puede asignar al tipo de referencia.
Esto generará una excepción de tiempo de ejecución si hay una que no sea de Apple en la canasta de frutas, como una naranja.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() }; foreach(Apple a in fruitBasket)
Esto filtra de forma segura la lista solo a las manzanas usando Enumerable.OfType
foreach(Apple a in fruitBasket.OfType<Apple>() )
fuente
IList<ListItem> illi = new List<ListItem>(); ListItem li = null; foreach (HroCategory value in listddlsubcategory) { listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id); li = new ListItem(); li.Text = value.Description; li.Value = value.Id.ToString(); illi.Add(li); IList<ListItem> newilli = new List<ListItem>(); newilli = SubCatagoryFunction(listddlsubcategoryext, "-->"); foreach (ListItem c in newilli) { illi.Add(c); } }
fuente
También se puede encontrar información útil sobre este tema en MSDN . Tomando la esencia de ese artículo:
La palabra clave foreach enumera una colección, ejecutando la declaración incrustada una vez para cada elemento de la colección:
foreach (var item in collection) { Console.WriteLine(item.ToString()); }
El compilador traduce el bucle foreach que se muestra en el ejemplo anterior en algo similar a esta construcción:
IEnumerator<int> enumerator = collection.GetEnumerator(); while (enumerator.MoveNext()) { var item = enumerator.Current; Console.WriteLine(item.ToString()); }
fuente
puedes probar esto ...
List<int> numbers = new List<int>(); numbers.Add(5); numbers.Add(15); numbers.Add(25); numbers.Add(35); Console.WriteLine("You are added total number: {0}",numbers.Count); foreach (int number in numbers) { Console.WriteLine("Your adding Number are: {0}", number); }
fuente