Является ли foreach чисто "синтаксическим сахаром"?
Компилятор компилирует цикл foreach
в нечто вроде цикла for
когда foreach
используется с массивом. И компилятор компилирует foreach
цикл в нечто вроде в while
цикла, когда foreach
используется с IEnumerable
или IEnumerable<T>
. Значит ли это, что foreach
- это чисто syntactic sugar
? Или в этом есть что-то сложное?
Знает ли CLR о foreach
? Есть ли что-то специально разработанное для foreach
в коде MSIL?
Ответы
Ответ 1
Это чисто синтаксический сахар, в котором вы можете получить такое же поведение без него, да. Многие другие вещи одинаковы... for
, while
и т.д. Чтобы неверно процитировать Архимеда: "Дайте мне if
и goto
, и я переведу код..."
Нет, у CLR нет понятия foreach
.
Ответ 2
Это синтаксический сахар. Однако обратите внимание, что foreach работает, вызывая GetEnumerator(), затем MoveNext() до тех пор, пока не будет возвращен какой-либо дополнительный элемент, а затем всегда вызывается Dispose() на счетчике, который он ранее получил. Если вы хотите сделать это одинаково, не забывайте, что Dispose()!
Кроме того, CLR выполняет некоторые трюки, связанные с получением перечислителя. См. здесь и здесь, например.
Ответ 3
foreach
является внутренним просто циклом while
, который вызывает методы в IEnumerator
.
Ответ 4
Это не просто синтаксический сахар, поскольку элементы в цикле foreach неизменяемы (неизменяемы). Причиной этого, как так любезно указал Дании, является то, что большинство коллекций будут использовать перечислитель в foreach, и это перечисление, которое имеет ограничение не дать вам обновить содержимое списка во время его перечисления.
то есть.
Foreach(String s in List<string>)
{
s = "f"; //this will throw an error.
}
Ответ 5
Да, это чисто сахар. Следующий код
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()
}