Jakie typy klas mogą używać foreach
pętli?
Odpowiedzi:
Właściwie, ściśle rzecz biorąc, wszystko, czego potrzebujesz, foreach
to GetEnumerator()
metoda publiczna , która zwraca coś z bool MoveNext()
metodą i ? Current {get;}
właściwością. Jednak najczęstszym znaczeniem tego jest „coś, co implementuje IEnumerable
/ IEnumerable<T>
, zwracając IEnumerator
/ IEnumerator<T>
.
W sposób dorozumiany, obejmuje to wszystko, narzędzia ICollection
/ ICollection<T>
, jak coś podobnego Collection<T>
, List<T>
tablice ( T[]
), itd. Tak więc każdego standardowego „zbiór danych” będzie generalnie wspierać foreach
.
W celu potwierdzenia pierwszego punktu, poniższe działa dobrze:
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);
}
}
}
Jak to działa?
Każda pętla, taka jak foreach(int i in obj) {...}
rodzaj, równa się:
var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
int i; // C# 5.0
i = tmp.Current;
{...} // your code
}
Istnieją jednak różnice. Na przykład, jeśli moduł wyliczający (tmp) obsługuje IDisposable
, jest również używany (podobnie jak using
).
Zwróć uwagę na różnicę w umieszczaniu deklaracji „ int i
” wewnątrz (C # 5,0) w porównaniu z zewnętrzną (w C # 4,0) pętli. Jest to ważne, jeśli używasz i
anonimowej metody / lambdy wewnątrz bloku kodu. Ale to już inna historia ;-p
for-loop
(widać to podczas pracy z IL).
Z MSDN :
foreach
Stwierdzenie powtarza grupę wbudowane instrukcje dla każdego elementu macierzy lub zbiór obiektów .foreach
Oświadczenie jest używany do iteracji kolekcji, aby uzyskać żądaną informację, ale nie powinny być wykorzystywane do zmiany zawartości kolekcji uniknąć nieprzewidywalnych skutków ubocznych. (podkreślenie moje)
Więc jeśli masz tablicę, możesz użyć instrukcji foreach do iteracji po tablicy, na przykład:
int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
foreach (int i in fibarray)
{
System.Console.WriteLine(i);
}
Możesz go również użyć do iteracji w List<T>
kolekcji, na przykład:
List<string> list = new List<string>();
foreach (string item in list)
{
Console.WriteLine(item);
}
Zgodnie z wpisem na blogu Duck Notation , używane jest pisanie kaczka.
Oto dokumentacja: Główny artykuł z tablicami z obiektami kolekcji
Należy zauważyć, że „Typ elementu kolekcji musi być możliwy do przekonwertowania na typ identyfikatora”. Czasami nie można tego sprawdzić w czasie kompilacji i może wygenerować wyjątek czasu wykonywania, jeśli typu wystąpienia nie można przypisać do typu referencyjnego.
Spowoduje to wygenerowanie wyjątku czasu wykonywania, jeśli w koszyku z owocami znajduje się produkt inny niż Apple, na przykład pomarańcza.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)
To bezpiecznie filtruje listę tylko do jabłek przy użyciu Enumerable.OfType
foreach(Apple a in fruitBasket.OfType<Apple>() )
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);
}
}
Przydatne informacje na ten temat można również znaleźć w witrynie MSDN . Biorąc esencję z tego artykułu:
Słowo kluczowe foreach wylicza kolekcję, wykonując instrukcję embedded raz dla każdego elementu w kolekcji:
foreach (var item in collection)
{
Console.WriteLine(item.ToString());
}
Kompilator tłumaczy pętlę foreach pokazaną w powyższym przykładzie na coś podobnego do tej konstrukcji:
IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
var item = enumerator.Current;
Console.WriteLine(item.ToString());
}
możesz spróbować tego ...
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);
}