Вход/Регистрация
ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
вернуться

Троелсен Эндрю

Шрифт:

 private Car[] carArray;

 …

 // Метод итератора.

 public IEnumerator GetEnumerator {

foreach (Car с in carArray) {

yield return c;

}

 }

}

Обратите внимание на то, что данная реализация GetEnumerator осуществляет "проход" по вложенным элементам, используя внутреннюю логику foreach, и возвращает объекты Car вызывающей стороне, используя новую синтаксическую конструкцию yield return. Ключевое слово yield используется для того, чтобы указать значение (или значения), возвращаемые конструкции foreach вызывающей стороны. Когда в программе встречается оператор yield return, сохраняется текущая позиция, и именно с этой позиции выполнение будет продолжено при следующем вызове итератора.

Когда компилятор C# обнаруживает метод итератора, в рамках области видимости соответствующего типа (в данном случае это Garage) динамически генерируется вложенный класс. Этот автоматически сгенерированный класс реализует интерфейсы IEnumerable и IEnumerator и указывает необходимые параметры членов GetEnumerator, MoveNext, Reset и Current. Если теперь загрузить данное приложение в ildasm.exe, то будет видно, что внутренняя реализация GetEnumerator в объекте Garage использует сгенерированный компилятором тип (который в данном примере получает имя ‹GetEnumerator›d__0).

.method public hidebysig instance class [mscorlib] System.Collections.IEnumerator GetEnumerator cil managed {

 …

 newobj instance void CustomEnumeratorWithYield.Garage/ '‹GetEnumerator›d__0'::.ctor(int32)

 …

} // end of method Garage::GetEnumerator

Явно, что от предложенного здесь определения метода итератора мы не получим большой пользы, поскольку наш тип Garage изначально реализовывал GetEnumerator, ссылаясь на внутренний тип System.Array. Но синтаксис итератора C# может сэкономить немало времени при построении более "экзотических" пользовательских контейнеров (например, бинарных деревьев), где приходится вручную реализовать интерфейсы IEnumerator и IEnumerable. В любом случае программный код вызывающей стороны при взаимодействии с методом итератора с использованием foreach оказывается одинаковым.

static void Main(string[] args) {

 Console.WriteLine("***** Забавы с методами итератора *****\n");

 Garage carLot = new Garage;

 foreach (Car с in carLot) {

Console.WriteLine("{0} имеет скорость {1} км/ч", с.PetName, с.CurrrSpeed);

 }

 Console.ReadLine;

}

Исходный код. Проект CustomEnumeratorWifhYield размещен в подкаталоге, соответствующем главе 7.

Создание клонируемых объектов (ICloneable)

Вы, должно быть, помните из главы 3, что System.Object определяет член с именем MemberwiseClone. Указанный метод используется для получения поверхностной копии объекта. Пользователи объекта не могут вызвать этот метод непосредственно (поскольку он является защищенным), но сам объект может вызвать этот метод в процессе клонирования. Для примера предположим, что у нас есть класс с именем Point (точка).

// Класс Point.

public class Point {

 // Открыты для простоты.

 public int x, у;

 public Point(int x, int y) { this.x = x; this.у = у; }

 public Point{}

 // Переопределение Object.ToString.

 public override string ToString { return string.Format("X = {0}; Y = {1}", x, у); }

}

С учетом того, что вы уже знаете о ссылочных типах и типах, характеризуемых значениями (см. главу 3), вы должны понимать, что в результате присваивания одной ссылочной переменной другой получаются две ссылки, указывающие на один и тот же объект в памяти. Поэтому следующее присваивание дает две ссылки на один и тот же объект Point в динамической памяти, и модификации любой из этих ссылок будут влиять на этот объект.

static void Main(string[] args) {

 // Две ссылки на один и тот же объект!

 Point p1 = new Point(50, 50);

 Point p2 = p1;

 р2.х = 0;

 Console.WriteLine(p1);

 Console.WriteLine(p2);

}

Чтобы обеспечить пользовательскому типу возможность возвращать копию этого типа вызывающей стороне, можно реализовать стандартный интерфейс ICloneable. Этот интерфейс определяет единственный метод с именем Clone.

public interface ICloneable {

  • Читать дальше
  • 1
  • ...
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: