Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

IEnumerable<T> и оператор foreach() [дубликат]

#c_sharp #foreach #ienumerable


        
             
                
                    
                        
                            На этот вопрос уже дан ответ здесь:
                            
                        
                    
                
                        
                            Работа цикла foreach, С#
                                
                                    (1 ответ)
                                
                        
                                Закрыт 2 года назад.
            
                    
Я реализовал простенький односвязный список сначало так :
Клас, производный от интерфейса IEnumerable

class MyList : IEnumerable
{
    public Goods head;
    public Goods tail;
    //add,remove и так далее
    public IEnumerator GetEnumerator()
    {
        Goods curr = head;
        while (curr != null)
        {
            yield return curr.Item;
            curr = curr.Next;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}


Затем его переписал его так, что бы он не был производным от интерфейса IEnumerable:

class MyList 
{
    public Goods head;
    public Goods tail;
    //add,remove и так далее
    public IEnumerator GetEnumerator()
    {
        Goods curr = head;
        while (curr != null)
        {
            yield return curr.Item;
            curr = curr.Next;
        }
   }
}


На MDSN написано :


  The foreach statement repeats a group of embedded statements for each element in
an array or an object collection that implements the IEnumerable or IEnumerable interface.


Второй класс не является производным от IEnumerable. Каким образом я тогда могу спокойно
по нему пройтись оператором foreach()?

MyList myList = new MyList();
myList.Add(10);
myList.Add(20);
foreach(var c in myList)
{
 Console.WriteLine(c);
}

    


Ответы

Ответ 1



Открываем документацию и читаем: Оператор foreach выполняет оператор или блок операторов для каждого элемента в экземпляре типа, который реализует интерфейс System.Collections.IEnumerable или System.Collections.Generic.IEnumerable. Оператор foreach не ограничивается этими типами. Он может применяться к экземпляру любого типа, который удовлетворяет следующим условиям: включает открытый метод GetEnumerator без параметров со следующим типом возвращаемого значения: класс, структура или тип интерфейса; тип возвращаемого значения метода GetEnumerator должен содержать открытое свойство Current и открытый метод MoveNext без параметров с типом возвращаемого значения Boolean. Таким образом, достаточно просто наличия подходящего метода GetEnumerator. Спецификация уточняет, что вот такой foreach foreach (V v in x) embedded_statement на этапе компиляции раскрывается в { E e = ((C)(x)).GetEnumerator(); try { while (e.MoveNext()) { V v = (V)(T)e.Current; embedded_statement } } finally { ... // Dispose e } } (C — тип коллекции, E — тип энумератора, V — тип значения элемента коллекции.) [Таким образом, всё происходит на этапе компиляции, рефлексия не применяется.]

Комментариев нет:

Отправить комментарий