Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка ПИ Программирование на С# _Хотов.docx
Скачиваний:
10
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
      1. Индексаторы и создание коллекций

Индексаторы позволяют индексировать объекты и использовать их как массивы. Фактически индексаторы позволяют нам создавать специальные хранилища объектов или коллекции. По форме они напоминают свойства со стандартными методамиget и set, которые возвращают и присваивают значение.

Посмотрим на примере. Допустим, у нас есть класс Book, представляющий книгу, и класс Library, который представляет библиотеку и используется для хранения набора книг. Используем индексаторы для определения класса Library:

class Program

{

static void Main(string[] args)

{

Library library = new Library();

Console.WriteLine(library[0].Name);

library[0] = new Book("Преступление и наказание");

Console.WriteLine(library[0].Name);

Console.ReadLine();

}

}

class Book

{

public Book(string name)

{

this.Name = name;

}

public string Name { get; set; }

}

class Library

{

Book[] books;

public Library()

{

books = new Book[] { new Book("Отцы и дети"), new Book("Война и мир"),

new Book("Евгений Онегин") };

}

public int Length

{

get { return books.Length; }

}

public Book this[int index]

{

get

{

return books[index];

}

set

{

books[index] = value;

}

}

}

В классе Library определен массив Book, к которому мы будем обращаться с помощью индексатора. А само определение индексатора напоминает свойство: public Book this[int index]. Здесь определяем, во-первых, тип возвращаемого или присваиваемого объекта, то есть Book. Во-вторых, определяем через параметр int index способ доступа к элементам.

И после этого в основной программе можно обращаться к объекту Library как к массиву: library[0].Name. Так как индексатор использует тип Book, то library[0] будет представлять объект Book.

Посмотрим более сложный пример. Допустим, у нас есть класс, в котором хранилище определено в виде двухмерного массива или матрицы:

class Matrix

{

private int[,] numbers = new int[,] { { 1, 2, 4 }, { 2, 3, 6 }, { 3, 4, 8 } };

public int this[int i, int j]

{

get

{

return numbers[i, j];

}

set

{

numbers[i, j] = value;

}

}

}

Теперь для определения индексатора используются два индекса - i и j. И в программе мы уже должны обращаться к объекту, используя два индекса:

Matrix matrix = new Matrix();

Console.WriteLine(matrix[0, 0]);

matrix[0, 0] = 111;

Console.WriteLine(matrix[0, 0]);

      1. Интерфейсы iEnumerable и iEnumerator

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

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

public interface IEnumerable

{

IEnumerator GetEnumerator();

}

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

public interface IEnumerator

{

bool MoveNext(); // перемещение на одну позицию вперед в контейнере элементов

object Current { get; } // текущий элемент в контейнере

void Reset(); // перемещение в начало контейнера

}

Возьмем пример с классом Library из прошлой темы и реализуем в этом классе интерфейс IEnumerable:

using System;

class Book

{

public Book(string name)

{

this.Name = name;

}

public string Name { get; set; }

}

class Library : IEnumerable

{

private Book[] books;

public Library()

{

books = new Book[] { new Book("Отцы и дети"), new Book("Война и мир"),

new Book("Евгений Онегин") };

}

public int Length

{

get { return books.Length; }

}

public Book this[int index]

{

get

{

return books[index];

}

set

{

books[index] = value;

}

}

// возвращаем перечислитель

IEnumerator IEnumerable.GetEnumerator()

{

return books.GetEnumerator();

}

}

class Program

{

static void Main(string[] args)

{

Library library = new Library();

foreach (Book b in library)

{

Console.WriteLine(b.Name);

}

Console.ReadLine();

}

}

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

IEnumerator IEnumerable.GetEnumerator()

{

return books.GetEnumerator();

}

И в программе мы сможем пройтись по объекту Library в цикле foreach.