Класс StringComparer
был подробно описан в главе 21 при рассмотрении вопросов сортировки и поиска в массивах. В этом классе реализуются интерфейсы IComparer, IComparer, IEqualityComparer
, а также IEqualityComparer
. Следовательно, экземпляр объекта типа StringComparer
может быть передан параметру типа IComparer
в качестве аргумента. В классе StringComparer
определяется несколько доступных только для чтения свойств, возвращающих экземпляр объекта типа StringComparer
, который поддерживает различные способы сравнения символьных строк. Как пояснялось в главе 21, к числу этих свойств относятся следующие: CurrentCulture, CurrentCulturelgnoreCase, InvariantCulture, InvariantCulturelgnoreCase, Ordinal
, а также OrdinallgnoreCase
. Все эти свойства можно использовать для явного указания способа сравнения символьных строк.
В качестве примера ниже показано, как коллекция типа SortedList
конструируется для хранения символьных строк, ключи которых сравниваются порядковым способом.
SortedList users =
new SortedList(StringComparer.Ordinal);
Доступ к коллекции с помощью перечислителя
К элементам коллекции нередко приходится обращаться циклически, например, для отображения каждого элемента коллекции. С этой целью можно, с одной стороны, организовать цикл foreach
, как было показано в приведенных выше примерах, а с другой — воспользоваться перечислителем. Перечислитель — это объект, который реализует необобщенный интерфейс IEnumerator
или обобщенный интерфейс IEnumerator
.
В интерфейсе IEnumerator
определяется одно свойство, Current
, необобщенная форма которого приведена ниже.
object Current { get; }
А в интерфейсе IEnumerator
объявляется следующая обобщенная форма свойства Current
.
Т Current { get; }
В обеих формах свойства Current
получается текущий перечисляемый элемент коллекции. Но поскольку свойство Current
доступно только для чтения, то перечислитель может служить только для извлечения, но не видоизменения объектов в коллекции.
В интерфейсе IEnumerator
определяются два метода. Первым из них является метод MoveNext()
, объявляемый следующим образом.
bool MoveNext()
При каждом вызове метода MoveNext()
текущее положение перечислителя смещается к следующему элементу коллекции. Этот метод возвращает логическое значение true
, если следующий элемент коллекции доступен, и логическое значение false
, если достигнут конец коллекции. Перед первым вызовом метода MoveNext()
значение свойства Current
оказывается неопределенным. (В принципе до первого вызова метода MoveNext()
перечислитель обращается к несуществующему элементу, который должен находиться перед первым элементом коллекции. Именно поэтому приходится вызывать метод MoveNext()
, чтобы перейти к первому элементу коллекции.)
Для установки перечислителя в исходное положение, соответствующее началу коллекции, вызывается приведенный ниже метод Reset()
.
void Reset()
После вызова метода Reset()
перечисление вновь начинается с самого начала коллекции. Поэтому, прежде чем получить первый элемент коллекции, следует вызвать метод MoveNext()
.
В интерфейсе IEnumerator
методы MoveNext()
и Reset()
действуют по тому же самому принципу.
Необходимо также обратить внимание на два следующих момента. Во-первых, перечислитель нельзя использовать для изменения содержимого перечисляемой с его помощью коллекции. Следовательно, перечислители действуют по отношению к коллекции как к доступной только для чтения. И во-вторых, любое изменение в перечисляемой коллекции делает перечислитель недействительным.
Применение обычного перечислителя
Прежде чем получить доступ к коллекции с помощью перечислителя, необходимо получить его. В каждом классе коллекции для этой цели предоставляется метод GetEnumerator()
, возвращающий перечислитель в начало коллекции. Используя этот перечислитель, можно получить доступ к любому элементу коллекции по очереди. В целом, для циклического обращения к содержимому коллекции с помощью перечислителя рекомендуется придерживаться приведенной ниже процедуры.
1. Получить перечислитель, устанавливаемый в начало коллекции, вызвав для этой коллекции метод GetEnumerator()
.
2. Организовать цикл, в котором вызывается метод MoveNext()
. Повторять цикл до тех пор, пока метод MoveNext()
возвращает логическое значение true
.
Читать дальше