Как работают циклы foreach в C #? - PullRequest
83 голосов
/ 30 декабря 2008

Какие типы классов могут использовать циклы foreach?

Ответы [ 7 ]

158 голосов
/ 30 декабря 2008

На самом деле, строго говоря, все, что вам нужно для использования foreach, - это открытый GetEnumerator() метод, который возвращает что-то с методом bool MoveNext() и свойством ? Current {get;}. Тем не менее, наиболее распространенным значением этого слова является "то, что реализует IEnumerable / IEnumerable<T>, возвращая IEnumerator / IEnumerator<T>.

Подразумевается, что это включает в себя все, что реализует ICollection / ICollection<T>, например что-либо вроде Collection<T>, List<T>, массивы (T[]) и т. Д. Таким образом, любой стандартный «сбор данных» обычно поддержка foreach.

Для доказательства первого пункта отлично работает следующее:

using System;
class Foo {
    public int Current { get; private set; }
    private int step;
    public bool MoveNext() {
        if (step >= 5) return false;
        Current = step++;
        return true;
    }
}
class Bar {
    public Foo GetEnumerator() { return new Foo(); }
}
static class Program {
    static void Main() {
        Bar bar = new Bar();
        foreach (int item in bar) {
            Console.WriteLine(item);
        }
    }
}

Как это работает?

Цикл foreach, такой как foreach(int i in obj) {...}, что-то вроде:

var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
    int i; // C# 5.0
    i = tmp.Current;
    {...} // your code
}

Однако, есть вариации. Например, если перечислитель (tmp) поддерживает IDisposable, он также используется (аналогично using).

Обратите внимание на разницу в размещении объявления "int i" внутри (C # 5.0) против снаружи (до C # 4.0) цикла , Это важно, если вы используете i в анонимном методе / лямбде внутри вашего кодового блока. Но это другая история; -p

6 голосов
/ 30 декабря 2008

С MSDN :

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

Итак, если у вас есть массив, вы можете использовать оператор foreach для итерации по массиву, например:

 int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
    foreach (int i in fibarray)
    {
        System.Console.WriteLine(i);
    }

Вы также можете использовать его для перебора коллекции List<T>, например:

List<string> list = new List<string>();

foreach (string item in list)
{
    Console.WriteLine(item);
}
4 голосов
/ 30 декабря 2008

Согласно сообщению в блоге Утиная нотация , используется типирование утки.

2 голосов
/ 30 декабря 2008

Вот документы: Основная статья С массивами С объектами коллекции

Важно отметить, что «тип элемента коллекции должен быть преобразован в тип идентификатора». Иногда это не может быть проверено во время компиляции и может генерировать исключение во время выполнения, если тип экземпляра не может быть назначен ссылочному типу.

Это сгенерирует исключение времени выполнения, если в корзине с фруктами не будет Apple, например апельсин.

List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)

Это безопасно фильтрует список только для яблок, используя Enumerable.OfType

foreach(Apple a in fruitBasket.OfType<Apple>() )
0 голосов
/ 24 апреля 2018

Полезную информацию по этому вопросу можно найти также на MSDN . Принимая суть из этой статьи:

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

foreach (var item in collection)
{
    Console.WriteLine(item.ToString());
}

Компилятор переводит цикл foreach, показанный в приведенном выше примере, во что-то похожее на эту конструкцию:

IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    Console.WriteLine(item.ToString());
}
0 голосов
/ 31 марта 2018

Вы можете попробовать это ...

List<int> numbers = new List<int>();
        numbers.Add(5);
        numbers.Add(15);
        numbers.Add(25);
        numbers.Add(35);

        Console.WriteLine("You are added total number: {0}",numbers.Count);
        foreach (int number in numbers)
        {
            Console.WriteLine("Your adding Number are: {0}", number);
        }
0 голосов
/ 17 марта 2017
IList<ListItem> illi = new List<ListItem>();
ListItem li = null;

foreach (HroCategory value in listddlsubcategory)
{
    listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id);
    li = new ListItem();
    li.Text = value.Description;
    li.Value = value.Id.ToString();
    illi.Add(li);
    IList<ListItem> newilli = new List<ListItem>();
    newilli = SubCatagoryFunction(listddlsubcategoryext, "-->");
    foreach (ListItem c in newilli)
    {
        illi.Add(c);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...