2014-01-31 5 views
0

Оператор foreach повторяет группу встроенных операторов для каждого элемента массива или коллекции объектов, которая реализует интерфейс System.Collections.IEnumerable или System.Collections.Generic.IEnumerable<T>.Какова связь между foreach и IEnumerable?

Я понимаю, что если мы хотим использовать foreach в коллекции объектов, нам нужно реализовать IEnumerable.

Я хочу понять, как реализация в IEnumerable позволяет использовать «foreach»?

Исходный код IEnumerable, похоже, имеет только одну функцию «GetEnumerator», и, очевидно, нет реализации, поскольку IEnumerable - это интерфейс. Итак, как ключевое слово foreach фактически использует интерфейс IEnumerable для перечисления?

Edit: Кроме того, пытаясь понять в этом контексте:

IEnumerable<Int> myNumbers = new IEnumerable<Int>(); 

Какой GetEnumerator() называется/используется здесь?

Edit 2:

Таким образом, ответ кажется:
1: утиная типизация - (. Спасибо @Alexei Левенков я принял @horrorcat в качестве ответа, потому что я могу принять только один :))
2. Я сделал очевидную ошибку в попытке создать конкретный экземпляр интерфейса (во второй части моего вопроса) - (спасибо @Gary Vass)

+2

Это просто вызывает метод. – SLaks

+1

Разработчик 'IEnumerable' реализует метод' GetEnumerator() ', foreach вызывает этот метод, а затем использует результирующий' IEnumerator' для итерации по элементам. – Lukazoid

+0

Возможно, вам следует прочитать [Интерфейсы (Руководство по программированию на C#)] (http://msdn.microsoft.com/en-us/library/ms173156.aspx) –

ответ

1

IEnumerable.GetEnumerator() возвращает объект перечисления (который реализует IEnumerator). У этого есть свойство «Текущий», который возвращает текущий элемент, и метод «MoveNext()», который переводит перечислитель на следующий элемент.

Это все, что требуется для цикла foreach, для выполнения команды foreach. Он просто присваивает переменной «Current» переменной, а затем выполняет каждый раз .MoveNext().

Обычно, когда вы реализуете IEnumerable в классе, вы знаете, откуда исходит источник.Так что если у вас есть класс, как этот

public class MyEnumerable 
{ 
    private List<string> items; 
} 

Реализация IEnumerable будет выглядеть следующим образом

public class MyEnumerable : IEnumerable<string> 
{ 
    private List<string> items; 

    public IEnumerator<string> GetEnumerator() 
    { 
     return items.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return items.GetEnumerator(); 
    } 
} 

Обратите внимание, что переписчик исходит из объекта списка, поэтому вам не придется беспокоиться о создавая перечислитель (хотя вы можете, если вам нужно, используя IEnumerator)

+0

Спасибо, это имеет смысл. Теперь, если я использую IEnumerable так: IEnumerable Сель = someFunctionWhichReturnsAnIenumerable) (или LINQ заявление) ( Тогда Еогеасп не имеет реализации для GetEnumerator, верно? (Поскольку исходный код IEnumerable имеет только пустое определение для Getenumerator, а не реализацию. Так где же он получает реализацию GetEnumerator, которая возвращает IEnumerator? – Gadam

1

foreach вызовов IEnumerable.GetEnumerator() (если коллекция реализует один) или внешний вид для метода GetEnumerator(), который возвращает duck-typed matching iterator class.

Чем итерации по элементам, используя результат GetEnumerator(), вызовите каждый элемент для ввода, указанный в первом параметре foreach.

+0

Что произойдет, если «коллекция не реализует один»? – Gadam

+0

@ Gadam - связанный ответ содержит подробности - он использует утиную печать для поиска необходимых методов в этом случае. –

0

как Lukazoid сказал: «Разработчик IEnumerable реализует метод GetEnumerator(), foreach вызывает этот метод, а затем использует полученный IEnumerator для итерации по элементам «.

foreach использует только интерфейс IEnumerable/IEnumerable <>, я думаю об этом, как C# кратчайшие для написания «только для чтения» для петли, которую вы можете использовать данные, но не редактировать его.

также я нашел это здесь, на StackOverflow //which may make this question a dup

What's going on behind the scene of the 'foreach' loop?

0

Foreach просто sytactic сахара для того, чтобы с помощью IEnumerable типов. Код типа:

foreach (var item in collection) 
{ 
    ... 
} 

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

using (var enumerator = collection.GetEnumerator()) 
{ 
    while (enumerator.MoveNext()) 
    { 
     var item = enumerator.Current; 
     // loop contents here 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^