2010-06-22 20 views
21

Logicznie rzecz biorąc, można by pomyśleć, że pętla foreach w C# będzie oceniać w tej samej kolejności, co inkrementująca się pętla. Eksperymentalnie to robi. Jednak wydaje się, że nie ma takiego potwierdzenia na stronie MSDN.Czy pętla foreach w C# gwarantuje kolejność oceny?

Czy jest to po prostu tak oczywista odpowiedź, że nie sądzili, aby umieścić tę informację na stronie? Czy istnieje możliwość, że będzie się zachowywać chaotycznie?

Odpowiedz

35

W przypadku tablic (należy pamiętać, że System.Array implementuje IEnumerable), uzyska dostęp do elementów w kolejności. W przypadku innych typów (IEnumerable lub posiadających GetEnumerator) uzyskuje dostęp do elementów w podanej kolejności, naprzemiennie MoveNext i Current.

Standardowe Zjednoczone (ECMA 364 §15.8.4)

„Kolejność foreach przechodzi elementów macierzy, jest następujący sposób: W układach jednowymiarowe elementy są przesuwany w zwiększaniu Palec, wychodząc z indeksem 0 i kończąc wskaźnik długości - 1. w tablic wielowymiarowych elementy ruch tak, że indeksy skrajnej prawej wymiar zwiększa , potem następny lewy wymiar , itd. Po lewej stronie. "

5

Za to, co warto, możesz dużo sprawdzić w Reflector. W mscorlib, System.Array implementuje IEnumerable (jak wspomniano), a Array#GetEnumerator zwraca ArrayEnumerator. Oto ciało ArrayEnumerator#MoveNext:

public bool MoveNext() 
{ 
    if (this._complete) 
    { 
     this.index = this.endIndex; 
     return false; 
    } 
    this.index++; 
    this.IncArray(); 
    return !this._complete; 
} 

To oczywiście jeden z przykładów, ale odpowiedź brzmi: to zależy do realizatora i można dowiedzieć się większość drogi pracują eksperymentalnie, albo przez kontrolę źródła, w niektórych przypadkach .

11

foreach jest zbudowany na szczycie IEnumerable<T> Umowa na wyliczający na MSDN mówi

Początkowo wyliczający jest umieszczony przed pierwszym elementem w kolekcji. ... Dlatego musisz wywołać metodę MoveNext, aby przenieść moduł wyliczający do pierwszego elementu kolekcji przed odczytaniem wartości Current.

Prąd zwraca ten sam obiekt do momentu wywołania funkcji MoveNext. MoveNext ustawia Current na następny element.

Więc jeśli zbiór bazowy ma jasną „pierwszy” elementu, a każdy element ma jasną „Next” elementu, jak to jest w przypadku tablic, listach i tak dalej, to można się spodziewać, że foreach zachowywać logicznie i stabilnie. Jeśli jest to coś w rodzaju zestawu, który nie ma pierwszej ani następnej sekwencji, to może zachowywać się niestabilnie, chociaż prawdopodobnie nie zmieniając stanu IEnumerable nawet kolekcje, które nie mają zdefiniowanej kolejności, będą spójne, ponieważ ich niespójność byłaby większa. praca!

3

Ostrzeżeniem na foreach są tablice hash, w których kolejność nie jest gwarantowana ze względu na ... klucze hash.

Powiązane problemy