Целостность цикла .NET 101

Я всегда был в замешательстве по этому поводу. Рассмотрим следующие циклы:

int [] list = new int [] { 1, 2, 3 };  
for (int i=0; i < list.Length; i++) { }  
foreach (int i in list) { }  
while (list.GetEnumerator().MoveNext()) { } // Yes, yes you wouldn't call GetEnumerator with the while. Actually never tried that.  
  • Приведенный выше [список] жестко запрограммирован. Если бы список был изменен извне, пока цикл выполнял итерации, что бы произошло?
  • Что, если [список] был свойством только для чтения, например. int List{get{return(new int [] {1,2,3});}}? Не нарушит ли это цикл. Если нет, будет ли он создавать новый экземпляр на каждой итерации?

person Raheel Khan    schedule 10.02.2012    source источник


Ответы (1)


Что ж:

  • Цикл for проверяет list.Length на каждой итерации; на самом деле вы не получаете доступ к list внутри цикла, поэтому содержимое не имеет значения
  • Цикл foreach использует только list для получения итератора; изменение его для ссылки на другой список не имело бы значения, но если бы вы изменили сам список структурно (например, добавив значение, если бы это действительно было List<int> вместо int[]), это сделало бы итератор недействительным
  • Ваш третий пример, как написано, будет продолжаться вечно, если список не будет очищен, учитывая, что каждый раз он будет получать новый итератор. Если вы хотите более разумное объяснение, опубликуйте более разумный код

По сути, вам нужно понять разницу между содержимым массива и изменением объекта, на который ссылается переменная, а затем дать нам очень конкретную ситуацию для объяснения. Однако в целом цикл foreach напрямую касается исходного выражения только один раз, когда он выбирает итератор, тогда как в цикле for нет никакой магии, и как часто к нему обращаются, просто зависит от кода - как условие, так и "шаг" часть цикла for выполняется на каждой итерации, поэтому, если вы обратитесь к переменной в любой из этих частей, вы увидите любые изменения...

person Jon Skeet    schedule 10.02.2012
comment
Еще один момент заключается в том, что для массива свойство Length является неизменным. Если кто-то вызывает Length для массива и получает определенное значение, все будущие вызовы Length для этого массива гарантированно возвращают одно и то же значение. Конечно, если у вас есть переменная экземпляра типа массива, и что-то изменяет эту переменную экземпляра, чтобы она указывала на другой массив, длина этого массива может отличаться от предыдущей. - person supercat; 11.02.2012