Перечислители, итераторы, IEnumerable - немного запутался - PullRequest
1 голос
/ 07 апреля 2011

Я несколько раз читал раздел "Итераторы / Перечислители" C # 3.0 в двух словах , но мне все еще трудно это понять. Исходя из их имен, я изначально думал, что итератор будет перебирать группу перечисляемых объектов. Я на правильном пути? Если так, то как насчет обычных универсальных коллекций, таких как List<T>? Создает ли List / использует Iterator во время некоторых его операций? Является ли T автоматически перечислимым? Есть ли актерский состав? Один имеет какое-либо отношение к другому?

В некотором родственном замечании, изучая MVC, я видел такой код:

public Article GetArticle(int id)
{
    return _siteDB.Articles.SingleOrDefault(a => a.ArticleID == id);
}

public IEnumerable<Article> GetArticle(string title)
{
    return _siteDB.Articles.Where(a => a.Title.StartsWith(title)).AsEnumerable<Article>();
}

Что дает возвращаемый тип IEnumerable<T>? 1010 *


РЕДАКТИРОВАТЬ: Хорошо, я думаю, я начинаю понимать. Моя путаница остается с итераторами. Книга описывает их как производителей Счетчиков. Я не понимаю, где это на самом деле происходит с yield return. Каждый выход создает новый перечислитель?

Ответы [ 3 ]

2 голосов
/ 07 апреля 2011

Тип IEnumerable дает вам IEnumerable :) Это интерфейсный метод определения GetEnumerator () , который возвращает IEnumerator. Вы можете вызывать метод столько раз, сколько хотите, и всегда получаете новый экземпляр IEnumerator.

IEnumerator имеет свойство Current и методы MoveNext () и Reset () , разрешающие перечисление коллекции. Само перечисление можно сделать, вызвав MoveNext () и прочитав свойство Current , если предыдущий вызов MoveNext () вернул true.

Хороший пример реализации и использования приведен в документации: http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx

1 голос
/ 07 апреля 2011

Посмотрим, смогу ли я ответить на этот вопрос.

Таким образом, List реализует IEnumerable, и не T, который должен его реализовывать, все в списке может быть повторено, например, с помощью forech или for. Если вы используете общий список, такой как List, это означает, что у вас есть список T, где T - это определенный вами тип объекта, это означает, что вам не нужно его приводить, но с другой стороны вы можете только поместить объекты того же типа в этом списке.

Код, который у вас есть, может означать ряд вещей:

1 - любая переменная, которая реализует IEnumerable, сможет содержать результат GetArticle, Пример:

List yourList = GetArticle("test");
Queue myQueue = GetArticle("test");

2 - фактическая обработка запроса будет отложена. Если вы вызываете Count, например, после вызова метода, то когда он фактически выполняется / разрешается.

3 - Из-за номера 2, если вы делаете это на БД, как предполагает код, то ваше соединение должно оставаться открытым до того момента, пока вы не воспользуетесь списком, в противном случае вы получите исключение.

Мне кажется, я ответил на вопросы.

1 голос
/ 07 апреля 2011

Исходя из их имен, я изначально думал, что итератор будет перебирать группу перечисляемых объектов. Я на правильном пути? Если так, то как насчет общих родовых коллекций, таких как список? Создает ли List / использует Iterator во время некоторых его операций?

Итератор - это способ реализации метода, возвращающего IEnumerable<T> - это действительно деталь реализации. Вместо того, чтобы создавать какой-то пользовательский класс для перечисления через коллекцию, вы можете использовать итератор для его реализации, и компилятор сделает за вас тяжелую работу.

Что дает мне возвращаемый тип IEnumerable?

Это в основном позволяет перечислять по типу. Например, второй метод (который я бы лично назвал GetArticles), позволил бы вам написать:

foreach(var article in GetArticle(theTitle))
{
   // Do something with article
}
...