C # Разница между Foreach и для (не производительность) - PullRequest
5 голосов
/ 09 октября 2010


Некоторое время назад я читал, что foreach работает с «копиями» объектов и, следовательно, может использоваться для поиска информации вместо ее обновления.Я не понимаю, так как это вполне возможно, чтобы просмотреть список классов и изменить его поле.Спасибо!

Ответы [ 5 ]

9 голосов
/ 09 октября 2010

Что вы можете прочитать, так это то, что вы не можете изменить коллекцию, перебирая ее, используя foreach, тогда как вы можете (если вы осторожны) использовать цикл for. Например:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        var list = new List<int> { 1, 4, 5, 6, 9, 10 };


        /* This version fails with an InvalidOperationException
        foreach (int x in list)
        {
            if (x < 5)
            {
                list.Add(100);
            }
            Console.WriteLine(x);
        }
         */

        // This version is okay
        for (int i = 0; i < list.Count; i++)
        {
            int x = list[i];
            if (x < 5)
            {
                list.Add(100);
            }
            Console.WriteLine(x);            
        }
    }
}

Если это , а не , на что вы ссылались, пожалуйста, дайте больше подробностей - трудно объяснить, что вы прочитали, не зная точно, что он сказал.

1 голос
/ 09 октября 2010

foreach использует IEnumerable для просмотра коллекции. Это делает невозможным изменение этой коллекции (удаление, добавление элементов), но вы по-прежнему можете изменять объекты внутри, если они являются ссылочными типами.

for - это простая комбинация простого цикла в сочетании с прямым доступом к элементам в коллекции. Пока этот цикл не блокируется, никаких блокировок нет.

1 голос
/ 09 октября 2010

foreach используйте Iterator, чтобы получить каждый элемент последовательности. Последовательность может быть Anything, которая реализует IEnumerable. IEnumerable не обязательно должен быть конечным (последовательность 0 1 2 3 4 ... 1000 ...) является IEnumerable.

for - это только конструкции C #, которые позволяют объявлять цикл (используется для выполнения всех видов операций, а не только для перебора коллекций)

Стоит отметить, что реализация Iterator в .NET для коллекций не поддерживает изменение последовательности во время итерации.

1 голос
/ 09 октября 2010

Вы не можете изменить элемент в foreach:

var list = new List<string>();
list.AddRange(new string[] { "A", "B", "C" });

foreach (var i in list)
{
    // compilation error: Cannot assign 'i' because it is a 'foreach iteration variable'
    i = "X";
}

Хотя при работе с for вы обращаетесь к элементу в списке с помощью его индекса, а не итератора, поэтомуВы можете изменить коллекцию.

0 голосов
/ 12 октября 2010

Сравните это с полем только для чтения:

private readonly List<int> MyList = new List<int>();

Теперь в этом коде я не могу сделать MyList = new List<int>(), так как это изменит то, на что указывает MyList, но я могу изменить список, на который указываетMyList.Add(3).

Аналогично, вы не можете изменить переменную, используемую итерацией foreach, но можете указать, к чему она относится:

foreach(List<int> lst in MyListOfLists)
{
  lst = new List<int>(); // not allowed
  lst.Add(3);  // allowed
}

Наконец, перечислитель, используемый для реализации foreach необязательно оставаться действительным, если используется базовая коллекция:

foreach(int x in SomeEnumerable)
{
    if(x != 0)
        SomeEnumerable.Add(0);
}

Если предположить, что Add изменяет SomeEnumerable, тогда вышеприведенный может работать, он может "работает" странным и трудным для понимания способом, и может вызвать исключение.С таким кодом поведение не гарантируется, и изменение коллекции во время перечисления считается неправильным по этой причине.

...