Программирование >>  Программирование с использованием ajax 

1 ... 93 94 95 [ 96 ] 97 98 99 ... 396


Реализация итератора

1. Создайте новое консольное приложение по имени СЬНЕхОЗ и сохраните его в каталоге C:\BegVCSharp\Chapterll.

2. Добавьте новый класс Primes и измените его код следующим образом:

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ChllExOS

public class Primes

private long min;

private long max;

public Primes 0 : this (2, 100)

public Primes (long minimum, long maximum) {

if (min < 2)

min = 2; else

min = minimum; max = maximum;

public lEnumerator GetEnumerator () {

for (long possiblePrime = min; possiblePrime <= max; possiblePrime++) {

bool is Prime = true;

for (long possibleFactor = 2; possibleFactor <= (long)Math.Floor(Math.Sqrt(possiblePrime)); possibleFactor++)

long remainderAfterDivision = possiblePrime % possibleFactor;

if (remainderAfterDivision = 0)

isPrime = false; break;

if (isPrime) {

yield return possiblePrime;

Когда в итераторе встречается такой оператор, обработка кода итератора тут же прекращается, равно как и выполнение использующего его цикла foreach.

Теперь пришла пора более сложного - и более полезного - примера. Поэтому в следующем разделе демонстрируется реализация итератора, получающего простые числа.



3. Измените код в файле Program.cs следующим образом:

static void Main(string [ ] args) {

Primes primesFrom2Tol000 = new Primes (2, 1000) ; foreach (long i in primesFrom2Tol000)

Console.WriteC{0} i) ; Console.ReadKey();

4. Запустите приложение. На рис. 11.4 показан результат, который должен получиться.


Рис. 11.4. Приложение ChllExOS в действии

Описание полученных результатов

Этот пример состоит из класса Primes, который позволяет проходить коллекцию простых чисел, находящихся между указанными верхним и нижним пределом. Этот класс инкапсулирует простые числа и использует для предоставления указанной функциональности итератор.

Код класса Primes начинается с определения базовых деталей, а именно - двух полей для хранения максимального и минимального значений, между которыми должен выполняться поиск, и конструкторов - для установки этих значений. Обратите внимание на то, что на минимальное значение накладывается ограничение, не позволяющее, чтобы оно было меньше 2. Такое ограничение действительно имеет смысл, поскольку 2 является наименьшим простым числом. Весь самый интересный код находится в методе GetEnumerator (). Сигнатура этого метода отвечает правилам оформления блока итератора, поскольку предусматривает возврат типа lEnumerator:

public lEnumerator GetEnumerator () {

Для извлечения простых чисел в определенных пределах необходимо протестировать каждое число по очереди, поэтому сначала идет цикл for:

for (long possiblePrime = min; possiblePrime <= max; possiblePrime++)

Поскольку признак, является число простым или нет, не известен, сначала делается предположение о том, что оно является таковым и выполняется проверка на предмет того, так ли это. Это подразумевает выполнение проверки на предмет того, является ли число между 2 и тем числом, которое получается при вычислении корня квадратного из тестируемого числа, множителем (factor). Если да, тогда число не является простым и потому осуществляется переход к следующему числу. Если же число действительно является простым, тогда оно передается циклу foreach с помощью оператора yield:



bool isPrime = true;

for (long possibleFactor = 2; possibleFactor <=

(long)Math.Floor(Math.Sqrt(possiblePrime)); possibleFactor++)

long remainderAfterDivision = possiblePrime % possibleFactor;

if (remainderAfterDivision == 0)

isPrime = false; break;

if (isPrime) {

yield return possiblePrime;

При указании слишком больших чисел для нижнего и верхнего пределов, в коде проявляется один интересный факт. Во время выполнения приложения результаты появляются по одному за раз, с паузами между ними, а не все одновременно. Это является свидетельством того, что код итератора возвращает результаты по одному, несмотря на тот факт, что никакого очевидного места завершения выполнения кода между вызовами yield нет. Однако за кулисами вызов yield все-таки действительно приводит к прерыванию выполнения кода, которое возобновляется при запрашивании следующего значения, т.е. тогда, когда у цикла foreach, в котором используется итератор, начинается новый прогон.

Итераторы и коллекции

Ранее было обещано объяснить то, как итераторы могут применяться для итерации по объектам, хранящимся в коллекции словарного типа, без привлечения объектов Dictionary Item. Напомним, как выглядит класс коллекции Animals:

public class Animals : DictionaryBase

public void Add(string newID, Animal newAnimal) {

Dictionary.Add(newID, newAnimal);

public void Remove(string animallD) {

Dictionary.Remove(animallD) ;

public Animals ()

public Animal this[string animallD] {

get {

return (Animal)Dictionary[animallD];

set {

Dictionary[animallD] = value;



1 ... 93 94 95 [ 96 ] 97 98 99 ... 396

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика