Getenumerator c как реализовать
Перейти к содержимому

Getenumerator c как реализовать

  • автор:

Getenumerator c как реализовать

Как мы увидели, основной для большинства коллекций является реализация интерфейсов IEnumerable и IEnumerator. Благодаря такой реализации мы можем перебирать объекты в цикле foreach :

foreach(var item in перечислимый_объект)

Перебираемая коллекция должна реализовать интерфейс IEnumerable.

Интерфейс IEnumerable имеет метод, возвращающий ссылку на другой интерфейс — перечислитель:

public interface IEnumerable

А интерфейс IEnumerator определяет функционал для перебора внутренних объектов в контейнере:

public interface IEnumerator < bool MoveNext(); // перемещение на одну позицию вперед в контейнере элементов object Current // текущий элемент в контейнере void Reset(); // перемещение в начало контейнера >

Метод MoveNext() перемещает указатель на текущий элемент на следующую позицию в последовательности. Если последовательность еще не закончилась, то возвращает true. Если же последовательность закончилась, то возвращается false.

Свойство Current возвращает объект в последовательности, на который указывает указатель.

Метод Reset() сбрасывает указатель позиции в начальное положение.

Каким именно образом будет осуществляться перемещение указателя и получение элементов зависит от реализации интерфейса. В различных реализациях логика может быть построена различным образом.

Например, без использования цикла foreach перебирем массив с помощью интерфейса IEnumerator:

using System.Collections; string[] people = ; IEnumerator peopleEnumerator = people.GetEnumerator(); // получаем IEnumerator while (peopleEnumerator.MoveNext()) // пока не будет возвращено false < string item = (string)peopleEnumerator.Current; // получаем элемент на текущей позиции Console.WriteLine(item); >peopleEnumerator.Reset(); // сбрасываем указатель в начало массива

Реализация IEnumerable и IEnumerator

Рассмотрим простешую реализацию IEnumerable на примере:

using System.Collections; Week week = new Week(); foreach (var day in week) < Console.WriteLine(day); >class Week : IEnumerable < string[] days = < "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" >; public IEnumerator GetEnumerator() => days.GetEnumerator(); >

В данном случае класс Week, который представляет неделю и хранит все дни недели, реализует интерфейс IEnumerable. Однако в данном случае мы поступили очень просто — вместо реализации IEnumerator мы просто возвращаем в методе GetEnumerator объект IEnumerator для массива.

public IEnumerator GetEnumerator() => days.GetEnumerator();

Благодаря этому мы можем перебрать все дни недели в цикле foreach.

В то же время стоит отметить, что для перебора коллекции через foreach в принципе необязательно реализовать интерфейс IEnumerable. Достаточно в классе определить публичный метод GetEnumerator , который бы возвращал объект IEnumerator. Например:

class Week < string[] days = < "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" >; public IEnumerator GetEnumerator() =>days.GetEnumerator(); >

Однако это было довольно просто — мы просто используем уже готовый перчислитель массива. Однако, возможно, потребуется задать свою собственную логику перебора объектов. Для этого реализуем интерфейс IEnumerator :

using System.Collections; class WeekEnumerator : IEnumerator < string[] days; int position = -1; public WeekEnumerator(string[] days) =>this.days = days; public object Current < get < if (position == -1 || position >= days.Length) throw new ArgumentException(); return days[position]; > > public bool MoveNext() < if (position < days.Length - 1) < position++; return true; >else return false; > public void Reset() => position = -1; > class Week < string[] days = < "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" >; public IEnumerator GetEnumerator() => new WeekEnumerator(days); >

Здесь теперь класс Week использует не встроенный перечислитель, а WeekEnumerator, который реализует IEnumerator.

Ключевой момент при реализации перечислителя — перемещения указателя на элемент. В классе WeekEnumerator для хранения текущей позиции определена переменная position. Следует учитывать, что в самом начале (в исходном состоянии) указатель должен указывать на позицию условно перед первым элементом. Когда будет производиться цикл foreach, то данный цикл вначале вызывает метод MoveNext и фактически перемещает указатель на одну позицию в перед и только затем обращается к свойству Current для получения элемента в текущей позиции.

Затем в программе мы можем аналогичным образом перебирать объект Week с помощью цикла foreach:

Week week = new Week(); foreach(var day in week)

Обобщенная версия IEnumerator

В примерах выше использовались необобщенные версии интерфейсов, однако мы также можем использовать их обобщенные двойники:

using System.Collections; class WeekEnumerator : IEnumerator  < string[] days; int position = -1; public WeekEnumerator(string[] days) =>this.days = days; public string Current < get < if (position == -1 || position >= days.Length) throw new ArgumentException(); return days[position]; > > object IEnumerator.Current => Current; public bool MoveNext() < if (position < days.Length - 1) < position++; return true; >else return false; > public void Reset() => position = -1; public void Dispose() < >> class Week < string[] days = < "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" >; public IEnumerator GetEnumerator() => new WeekEnumerator(days); >

В данном случае реализуем интерфейс IEnumerator , соответственно в свойстве Current нам надо возвратить объект string. В этом случае при переборе в цикле foreach перебираемые объекты будут автоматически представлять тип string :

Week week = new Week(); foreach (string day in week)

IEnumerable , C#

Компилятор упорно выдает ошибку : . не реализуется член интерфейса «System.Collections.IEnumerable.GetEnumerator()» Не совсем понятно , как можно реализовать метод IEnumerable.GetEnumerator() ведь IEnumerable обобщенный интерфейс и нужно указывать тип коллекции(что я и делал). Заранее спасибо.

Отслеживать
задан 20 янв 2012 в 21:10
370 1 1 золотой знак 12 12 серебряных знаков 33 33 бронзовых знака

Понимаете в том то и дело : я пробовал реализовать 2-ой метод ,но компилятор сразу красным подчеркивает слово IEnumerator , если не указывать тип T . Наверное нагляднее будет конкретный кусок кода показать : public class garage : IEnumerable < private Sport_car[] car_list; IEnumeratorIEnumerable.GetEnumerator() < return (IEnumerator)car_list.GetEnumerator(); > IEnumerator IEnumerable.GetEnumerator() < return car_list.GetEnumerator(); >..

20 янв 2012 в 23:09

Пишет , что использование универсального типа «System.Collection.Generic.IEnumerator» требует аргумента типа «1» То есть нельзя даже просто написать IEnumerator почему-то

20 янв 2012 в 23:16

Исправьте IEnumerator на System.Collections.IEnumerator , либо добавьте соответствующий using . Inumerator и IEnumerator это разные типы, они находятся в разных пространствах имён, однако второй интерфейс требует реализации первого.

20 янв 2012 в 23:59

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Интерфейс, к-й вы реализуете в свою очередь реализует не типизированный IEnumerable:

public interface IEnumerable : IEnumerable < IEnumeratorGetEnumerator(); > public interface IEnumerator : IDisposable, IEnumerator < T Current < get; >> public interface IEnumerator < object Current < get; >bool MoveNext(); void Reset(); > 

Следовательно вам необходимо реализовать и его «внутренности», а именно еще один метод GetEnumerator() и IEnumerator:

using System.Collections; using System.Collections.Generic; public class GarageEnumerator : IEnumerator  < private readonly IEnumerator enumerator; public GarageEnumerator(IEnumerator enumerator) < this.enumerator = enumerator; >public void Dispose() < >public bool MoveNext() < return enumerator.MoveNext(); >public void Reset() < enumerator.Reset(); >public T Current < get < return (T)enumerator.Current; >> object IEnumerator.Current < get < return Current; >> > public class Garage : IEnumerable  < private readonly T[] carList; //initialization ! public IEnumeratorGetEnumerator() < return new GarageEnumerator(carList.GetEnumerator()); > IEnumerator IEnumerable.GetEnumerator() < return GetEnumerator(); >> 

А вообще пользуйтесь встроенными средствами в VS — она может сделать ето за вас.

UPDATE: начиная с 3.5 фреймворка можно подключить:

using System.Linq; 
public class Garage : IEnumerable  < private readonly T[] carList = new T[10]; //initialization ! public IEnumeratorGetEnumerator() < return carList.Cast().GetEnumerator(); > IEnumerator IEnumerable.GetEnumerator() < return GetEnumerator(); >> 

Getenumerator c как реализовать

Коллеги, хотел бы реализовать на С++ COM объект, который можно было бы в C# обойти с помощью foreach
Нашел статью http://www.rsdn.ru/article/com/comcoll.xml

Автор(ы): Владислав Чистяков

Но когда так реализовал, у меня компилятор стал жаловаться, что в моём объекте нет GetEnumerator, когда его добавил, стал жаловаться на отсутвие MoveNext.
Мне кажется, я куда-то не туда копаю.
Вопрос простой — как на С++ релизовать нечто, что можно будет в C# обойти с помощью foraech
Заранее спасибо.

Re: Реализация foreach

От: Rakafon http://rakafon.blogspot.com/
Дата: 28.12.10 08:31
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Вопрос простой — как на С++ релизовать нечто, что можно будет в C# обойти с помощью foraech
А>Заранее спасибо.

Написать это «нечно» на managed C++, ведь всё равно, кроме как в .NET это нигде не заюзать.

«Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы.» (c) Мейер Ансельм Ротшильд , банкир.

Re[2]: Реализация foreach

От: Artem.shi
Дата: 28.12.10 08:55
Оценка:

Здравствуйте, Rakafon, Вы писали:

R>Написать это «нечно» на managed C++, ведь всё равно, кроме как в .NET это нигде не заюзать.

Я это и пытаюсь сделать.
Не пойму, зачем нужен метод GetEnumerator, и какого типа данные он должен возвращать.
Судя по документации, итератор ходит с помощью MoveNext, Reset? Current и Count.
http://msdn.microsoft.com/ru-ru/library/system.collections.ienumerable.getenumerator(v=VS.90).aspx?appId=Dev10IDEF1&l=RU-RU&k=k(IENUMERABLE);k(DevLang-«C++»);k(TargetOS-WINDOWS)&rd=true

Re[3]: Реализация foreach

От: dcb-BanDos
Дата: 28.12.10 10:15
Оценка: 1 (1)

Здравствуйте, Artem.shi, Вы писали:

AS>Здравствуйте, Rakafon, Вы писали:

Переложи на COM подобный код:

using System.Collections; // Declare the Tokens class: public class Tokens : IEnumerable < private string[] elements; Tokens(string source, char[] delimiters) < // Parse the string into tokens: elements = source.Split(delimiters); > // IEnumerable Interface Implementation: // Declaration of the GetEnumerator() method // required by IEnumerable public IEnumerator GetEnumerator() < return new TokenEnumerator(this); > // Inner class implements IEnumerator interface: private class TokenEnumerator : IEnumerator < private int position = -1; private Tokens t; public TokenEnumerator(Tokens t) < this.t = t; > // Declare the MoveNext method required by IEnumerator: public bool MoveNext() < if (position < t.elements.Length - 1) < position++; return true; > else < return false; > > // Declare the Reset method required by IEnumerator: public void Reset() < position = -1; >// Declare the Current property required by IEnumerator: public object Current < get < return t.elements[position]; > > >

Ничто не ограничивает полет мысли программиста так, как компилятор.
Re[4]: Реализация foreach

От: Artem.shi
Дата: 28.12.10 11:41
Оценка:

Здравствуйте, dcb-BanDos, Вы писали:

Спасибо, в принципи, такой вариант меня устраивает.

StringList GetEnumerator — метод

Gets an enumerator that iterates through the elements of the collection.

Пространство имён: Tessa.Exchange.WebServices.Data
Сборка: Tessa.Server (в Tessa.Server.dll) Версия: 3.5.0.19

Синтаксис

public IEnumeratorstring> GetEnumerator()
Public Function GetEnumerator As IEnumerator(Of String)
public: virtual IEnumeratorString^>^ GetEnumerator() sealed
abstract GetEnumerator : unit -> IEnumeratorstring> override GetEnumerator : unit -> IEnumeratorstring>
Возвращаемое значение

Тип: IEnumerator String
An IEnumerator for the collection.

Реализации

См. также

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *