Пошаговое руководство. Реализация IEnumerable(Of T) в Visual Basic
Статья
Интерфейс IEnumerable<T> реализуется классами, которые могут возвращать последовательность значений по одному элементу за один раз.Преимущество возвращения данных по одному элементу за один раз состоит в том, что при этом отсутствует необходимость загружать в память весь набор данных для работы с ними.Можно ограничиться использованием объема памяти, достаточного для загрузки одного элемента данных.Классы, реализующие интерфейс IEnumerable(T), могут использоваться совместно с циклами For Each или запросами LINQ.
Для примера возьмем приложение, которое должно читать большой текстовый файл и возвращать каждую строку из этого файла, отвечающую конкретным условиям поиска.Чтобы возвращать отвечающие заданным условиям строки из файла, приложение использует запрос LINQ.Чтобы опросить содержимое файла с помощью запроса LINQ, приложение могло бы загрузить это содержимое в массив или коллекцию.Однако загрузка целого файла в массив или коллекцию приведет к использованию значительно большего объема памяти, нежели необходимо.Вместо этого запрос LINQ может опросить содержимое файла с помощью перечислимого класса, возвращая только значения, соответствующие условиям поиска.Запросы, возвращающие только ограниченное число соответствующих значений, потребляют намного меньше памяти.
Для представления исходных данных как перечислимых можно создать класс, реализующий интерфейс IEnumerable<T>.Классу, реализующему интерфейс IEnumerable(T), потребуется другой класс, который реализует интерфейс IEnumerator<T> для итерации по исходным данным.Эти два класса позволяют последовательно возвращать элементы данных в виде определенного типа.
В этом пошаговом руководстве создается класс, реализующий интерфейс IEnumerable(Of String), и класс, который реализует интерфейс IEnumerator(Of String), которые могут использоваться для считывания текстового файла по одной строке за один раз.
Примечание
На вашем компьютере названия некоторых элементов интерфейса пользователя Visual Studio или их расположение могут отличаться от указанных в нижеследующих инструкциях. Это зависит от имеющегося выпуска Visual Studio и используемых параметров. Дополнительные сведения см. в разделе Параметры Visual Studio.
Создание перечислимого класса
Чтобы создать проект перечислимого класса, выполните следующие действия:
В Visual Basic в меню Файл последовательно выберите пункты Создать и Проект.
Убедитесь, что в диалоговом окне Новый проект в области Типы проектов выбран пункт Windows.В области Шаблоны выберите пункт Библиотека классов.В поле Имя введите StreamReaderEnumerable и нажмите кнопку ОК.Появится новый проект.
В обозревателе решений щелкните правой кнопкой мыши файл Class1.vb и выберите команду Переименовать.Переименуйте файл в StreamReaderEnumerable.vb и нажмите клавишу ВВОД.При переименовании файла класс также будет переименован в StreamReaderEnumerable.Этот класс будет реализовывать интерфейс IEnumerable(Of String).
Щелкните правой кнопкой мыши проект StreamReaderEnumerable, выберите команду Добавить и пункт Создать элемент.Выберите шаблон Класс.В поле Имя введите StreamReaderEnumerator.vb и нажмите кнопку ОК.
Первый класс в этом проекте — перечислимый класс, который реализует интерфейс IEnumerable(Of String).Этот универсальный интерфейс реализует интерфейс IEnumerable и предоставляет потребителям этого класса гарантированный доступ к значениям, тип которых задан как String.
Добавление кода для реализации IEnumerable
Откройте файл StreamReaderEnumerable.vb.
В строке после Public Class StreamReaderEnumerable введите следующее и нажмите клавишу ВВОД.
Visual Basic автоматически заполняет класс членами, необходимыми для интерфейса IEnumerable(Of String).
Этот перечислимый класс будет читать строки текстового файла одну за другой.Добавьте в класс следующий код, чтобы предоставить открытый конструктор, который принимает путь к файлу в качестве входного параметра.
Реализация метода GetEnumerator интерфейса IEnumerable(Of String) будет возвращать новый экземпляр класса StreamReaderEnumerator.Реализацию метода GetEnumerator интерфейса IEnumerable можно сделать закрытой (Private), поскольку требуется предоставить доступ только членам интерфейса IEnumerable(Of String).Замените код, созданный Visual Basic для методов GetEnumerator, следующим кодом.
Visual Basic автоматически заполняет класс членами, необходимыми для интерфейса IEnumerator(Of String).
Класс перечислителя открывает текстовый файл и выполняет файловые операции ввода-вывода, считывая строки из файла.Добавьте в класс следующий код, чтобы предоставить открытый конструктор, который принимает путь к файлу как входной параметр и открывает текстовый файл для чтения.
Свойства Current для интерфейсов IEnumerator(Of String) и IEnumerator возвращают текущий элемент из текстового файла в качестве объекта типа String.Реализацию свойства Current интерфейса IEnumerator можно сделать закрытой (Private), поскольку требуется предоставить доступ только членам интерфейса IEnumerator(Of String).Замените код, созданный Visual Basic для свойств Current, следующим кодом.
Метод MoveNext интерфейса IEnumerator переходит к следующему элементу в текстовом файле и обновляет значение, возвращаемое свойством Current.Если элементов для чтения не осталось, метод MoveNext возвращает значение False; в противном случае метод MoveNext возвращает значение True.Добавьте следующий код в метод MoveNext.
Метод Reset интерфейса IEnumerator дает итератору команду перейти в начало текстового файла и очищает значение текущего элемента.Добавьте следующий код в метод Reset.
Метод Dispose интерфейса IEnumerator гарантирует, что все неуправляемые ресурсы будут освобождены до уничтожения итератора.Дескриптор файла, используемый объектом StreamReader, является неуправляемым ресурсом, который должен быть закрыт до уничтожения экземпляра итератора.Замените код, созданный Visual Basic для метода Dispose, следующим кодом.
Перечислимый класс может использоваться в коде совместно с управляющими структурами, для которых требуется объект, реализующий интерфейс IEnumerable, например с циклом For Next или запросом LINQ.В следующем примере показан пример использования StreamReaderEnumerable в запросе LINQ.
Dim adminRequests =
From line In New StreamReaderEnumerable("..\..\log.txt")
Where line.Contains("admin.aspx 401")
Dim results = adminRequests.ToList()