Является ли foreach чисто «синтаксическим сахаром»? - PullRequest
13 голосов
/ 28 апреля 2011

Компилятор компилирует цикл foreach в нечто вроде цикла for, когда foreach используется с массивом.И компилятор компилирует цикл foreach в нечто вроде цикла while, когда foreach используется с IEnumerable или IEnumerable<T>.Значит ли это, что foreach это чисто syntactic sugar?Или в этом что-то сложное?

Знает ли CLR о foreach?Есть ли что-то специально разработанное для foreach в коде MSIL?

Ответы [ 5 ]

27 голосов
/ 28 апреля 2011

Это чисто синтаксический сахар в том смысле, что без него можно получить то же поведение, да.Многие другие вещи такие же ... for, while и т. Д. ... Чтобы неправильно цитировать Архимеда: "Дайте мне if и goto, и я переместу код ..."

Нет, CLR не имеет понятия foreach.

10 голосов
/ 28 апреля 2011

Это синтаксический сахар.Тем не менее, обратите внимание, что foreach работает, вызывая GetEnumerator (), затем MoveNext () до тех пор, пока не будет возвращен другой элемент, а затем всегда вызывает Dispose () для перечисленного ранее перечислителя.Если вы хотите сделать то же самое, не забывайте, что Dispose ()!

Кроме того, CLR выполняет некоторые приемы, связанные с получением перечислителя.См. здесь и здесь , например.

2 голосов
/ 28 апреля 2011

foreach внутренне является просто циклом while, который вызывает методы в IEnumerator.

0 голосов
/ 28 апреля 2019

Да, это чисто сахар.Следующий код

    var MyList = new List<int>() { 10 , 20 , 30 , 40, 50} ;  
    foreach(int i in MyList) 
    {
        Console.WriteLine(i);
    }

переводится в компилятор как:

Ienumrator<int> rator = MyList.GetEnumrator();

try{
   while(rator.MoveNext())
{
    int i = rator.Current; 
    Console.WriteLine(i); 
}
}
finally{
rator.Dispose()
}
0 голосов
/ 28 апреля 2011

Это не просто синтаксический сахар, поскольку элементы в цикле foreach неизменны (неизменяемы). Причина этого, как любезно указал Даниэль, состоит в том, что большинство коллекций будет использовать перечислитель в foreach, и именно перечислитель имеет ограничение, не позволяющее обновлять содержимое списка во время его перечисления. 1001 *

т.е.

Foreach(String s in List<string>)
{
   s = "f";  //this will throw an error.
}
...