Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.pdf
Скачиваний:
66
Добавлен:
11.05.2015
Размер:
1.73 Mб
Скачать

public class Range

{

public int Low { get; set; } public int High { get; set; }

public IEnumerable<int> GetNumbers()

{

for (int counter = Low; counter <= High; counter++)

{

yield return counter;

}

}

}

Используем класс Range следующим образом:

var range = new Range {Low = 0, High = 10}; var enumerator = range.GetNumbers(); foreach (int number in enumerator)

{

Console.WriteLine(number);

}

На консоль будут выведены числа от 0 до 10. Интересно, что если изменить объект range после получения перечислителя enumerator, это повлияет на выполнение цикла foreach. Следующий код выводит числа от 0 до 5.

var range = new Range {Low = 0, High = 10}; var enumerator = range.GetNumbers();

range.High = 5; // изменяем свойство объекта range foreach (int number in enumerator)

{

Console.WriteLine(number);

}

Возможности итераторов широко используются в технологии LINQ to Objects, которая будет описана далее.

9. Стандартные интерфейсы коллекций

Платформа .NET включает большой набор типов для предоставления стандартных коллекций – списков, множеств, словарей. Эти типы можно разделить на несколько категорий: базовые интерфейсы и вспомогательные классы, классы для коллекций-списков и словарей, набор классов для построения собственных коллекций. Типы сгруппированы в следующие пространства имён:

1. System.Collections – коллекции, в которых элемент коллекции пред-

ставлен как object (слаботипизированные коллекции).

2. System.Collections.Specialized – специальные коллекции.

32

3. System.Collections.Generic – универсальные классы и интерфейсы коллекций.

4. System.Collections.ObjectModel – базовые и вспомогательные типы, ко-

торые могут применяться для построения пользовательских коллекций.

5. System.Collections.Concurrent – коллекции для использования в мно-

гопоточных приложениях.

Рис. 3. Стандартные интерфейсы коллекций.

Опишем набор интерфейсов, реализуемых практически всеми типами коллекций. Основу набора составляют интерфейсы IEnumerable<T> и IEnumerable. Они отражают фундаментальное свойство любой коллекции – возможность перечислить её элементы. Слаботипизированные словари реализуют интерфейс

IDictionaryEnumerator для перебора пар «ключ-значение» (DictionaryEntry

вспомогательная структура, у которой определены свойства Key и Value).

public interface IDictionaryEnumerator : IEnumerator

{

DictionaryEntry Entry { get; } object Key { get; }

object Value { get; }

}

33

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

public interface ICollection : IEnumerable

{

// метод

void CopyTo(Array array, int index);

// свойства

int Count { get; }

bool IsSynchronized { get; } object SyncRoot { get; }

}

Универсальный интерфейс ICollection<T> также поддерживает свойство для количества элементов. Кроме этого, он предоставляет методы для добавления и удаления элементов, копирования элементов в массив, поиска элемента.

public interface ICollection<T> : IEnumerable<T>

{

// методы

void Add(T item); void Clear();

bool Contains(T item);

void CopyTo(T[] array, int arrayIndex); bool Remove(T item);

// свойства

int Count { get; }

bool IsReadOnly { get; }

}

Интерфейс IList описывает набор данных, которые проецируются на массив. Дополнительно к функциональности, унаследованной от IEnumerable и ICollection, интерфейс IList позволяет обращаться к элементу по индексу, добавлять, удалять и искать элементы.

public interface IList : ICollection

{

// методы

int Add(object value); void Clear();

bool Contains(object value); int IndexOf(object value);

void Insert(int index, object value); void Remove(object value);

void RemoveAt(int index);

34

// свойства

bool IsFixedSize { get; } bool IsReadOnly { get; }

object this[int index] { get; set; }

}

Возможности интерфейса IList<T> тождественны возможностям IList.

public interface IList<T> : ICollection<T>

{

// методы

int IndexOf(T item);

void Insert(int index, T item); void RemoveAt(int index);

// свойство

T this[int index] { get; set; }

}

В качестве примера работы с интерфейсом IList<T> рассмотрим метод Permutate(), генерирующий все перестановки указанного набора данных.

public static IEnumerable<IList<T>> Permutate<T>(IList<T> sequence, int count)

{

if (count == 1)

{

yield return sequence;

}

else

{

for (var i = 0; i < count; i++)

{

foreach (var perm in Permutate(sequence, count - 1))

{

yield return perm;

}

// циклический сдвиг sequence T last = sequence[count - 1]; sequence.RemoveAt(count - 1); sequence.Insert(0, last);

}

}

}

Интерфейсы IDictionary и IDictionary<TKey, TValue> определяют прото-

кол взаимодействия для коллекций-словарей (KeyValuePair<TKey, TValue> – это вспомогательная структура, у которой определены свойства Key и Value).

35

public interface IDictionary : ICollection

{

// методы

void Add(object key, object value); void Clear();

bool Contains(object key); IDictionaryEnumerator GetEnumerator(); void Remove(object key);

// свойства

bool IsFixedSize { get; } bool IsReadOnly { get; }

object this[object key] { get; set; }

ICollection Keys { get; }

//

все

ключи словаря

ICollection Values { get; }

//

все

значения словаря

}

 

 

 

public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>

{

// методы

void Add(TKey key, TValue value); bool ContainsKey(TKey key);

bool Remove(TKey key);

bool TryGetValue(TKey key, out TValue value);

// свойства

TValue this[TKey key] { get; set; } ICollection<TKey> Keys { get; } ICollection<TValue> Values { get; }

}

Для работы с коллекциями-множествами предназначен интерфейс ISet<T>. Его набор методов отражает типичные операции для множеств.

public interface ISet<T> : ICollection<T>

{

bool Add(T item);

void ExceptWith(IEnumerable<T> other); void IntersectWith(IEnumerable<T> other);

bool IsProperSubsetOf(IEnumerable<T> other); bool IsProperSupersetOf(IEnumerable<T> other); bool IsSubsetOf(IEnumerable<T> other);

bool IsSupersetOf(IEnumerable<T> other); bool Overlaps(IEnumerable<T> other); bool SetEquals(IEnumerable<T> other);

void SymmetricExceptWith(IEnumerable<T> other); void UnionWith(IEnumerable<T> other);

}

36