Главная страница
Навигация по странице:

  • Свойство

  • Интерфейс

  • Метод

  • Интерфейсы IEnumerable, IEnumerator и IDictionaryEnumerator

  • Интерфейс IHashCodeProvider

  • Структура DictionaryEntry

  • Классы коллекций общего назначения

  • Класс

  • Справочник по C# Герберт Шилдт ббк 32. 973. 26018 75 Ш57 удк 681 07 Издательский дом "Вильямс" Зав редакцией


    Скачать 5.05 Mb.
    НазваниеСправочник по C# Герберт Шилдт ббк 32. 973. 26018 75 Ш57 удк 681 07 Издательский дом "Вильямс" Зав редакцией
    АнкорC #.pdf
    Дата08.12.2017
    Размер5.05 Mb.
    Формат файлаpdf
    Имя файлаC #.pdf
    ТипСправочник
    #10795
    страница41 из 52
    1   ...   37   38   39   40   41   42   43   44   ...   52
    Глава 22
    Работа с коллекциями

    Глава 22. Работа с коллекциями
    611
    C# под коллекцией понимается группа объектов. Пространство имен
    System.Collections содержит множество интерфейсов и классов, которые определяют и реализуют коллекции различных типов. Коллекции упрощают программирование, предлагая уже готовые решения для построения структур данных, разработка которых “с нуля” отличается большой трудоемкостью. Речь идет о встроенных коллекциях, которые поддерживают, например, функционирование стеков, очередей и хеш- таблиц. Коллекции пользуются большой популярностью у всех C#-программистов.
    Обзор коллекций
    Основное достоинство коллекций состоит в том, что они стандартизируют способ обработки групп объектов в прикладных программах. Все коллекции разработаны на основе набора четко определенных интерфейсов. Ряд встроенных реализаций таких интерфейсов, как
    ArrayList
    ,
    Hashtable
    ,
    Stack и
    Queue
    , вы можете использовать “как есть”. У каждого программиста также есть возможность реализовать собственную коллекцию, но в большинстве случаев достаточно встроенных.
    Среда .NET Framework поддерживает три основных типа коллекций: общего назначения, специализированные и ориентированные на побитовую организацию данных.
    Коллекции общего назначения реализуют ряд основных структур данных, включая динамический массив, стек и очередь. Сюда также относятся словари, предназначенные для хранения пар ключ/значение. Коллекции общего назначения работают с данными типа object, поэтому их можно использовать для хранения данных любого типа.
    Коллекции специального назначения ориентированы на обработку данных конкретного типа или на обработку уникальным способом. Например, существуют специализированные коллекции, предназначенные только для обработки строк или однонаправленного списка.
    Классы коллекций, ориентированных на побитовую организацию данных, служат для хранения групп битов. Коллекции этой категории поддерживают такой набор операций, который не характерен для коллекций других типов. Например, в известной многим бит- ориентированной коллекции
    BitArray определены такие побитовые операции, как И и исключающее ИЛИ.
    Основополагающим для всех коллекций является реализация перечислителя
    (нумератора), который поддерживается интерфейсами
    IEnumerator и
    IEnumerable
    Перечислитель обеспечивает стандартизованный способ поэлементного доступа к содержимому коллекции. Поскольку каждая коллекция должна реализовать интерфейс
    IEnumerable
    , к элементам любого класса коллекции можно получить доступ с помощью методов, определенных в интерфейсе
    IEnumerator
    . Следовательно, после внесения небольших изменений код, который позволяет циклически опрашивать коллекцию одного типа, можно успешно использовать для циклического опроса коллекции другого типа.
    Интересно отметить, что содержимое коллекции любого типа можно опросить с помощью нумератора, используемого в цикле foreach
    И еще. Если вы знакомы со средствами C++-программирования, то вам будет интересно узнать, что C#-классы коллекций по сути аналогичны классам стандартной библиотеки шаблонов (Standard Template Library — STL), определенной в C++. То, что в
    C++ называется контейнером, в C# именуется коллекцией. То же справедливо и для Java.
    Если вы знакомы с Java-средой Collections Framework, то очень легко освоите использование C#-коллекций.
    В

    612
    Часть II. Библиотека C#
    Интерфейсы коллекций
    В пространстве имен
    System.Collections определено множество интерфейсов.
    Но мы начнем именно с интерфейсов коллекций, поскольку они определяют функции, общие для всех классов коллекций. Интерфейсы, которые поддерживают коллекции, приведены в табл. 22.1. А в следующих разделах подробно рассматривается каждый интерфейс.
    Интерфейс ICollection
    Интерфейс
    ICollection можно назвать фундаментом, на котором построены все коллекции. В нем объявлены основные методы и свойства, без которых не может обойтись ни одна коллекция. Он наследует интерфейс
    IEnumerable
    . Не зная сути интерфейса
    ICollection
    , невозможно понять механизм действия коллекции.
    В интерфейсе
    ICollection определены следующие свойства:
    Свойство
    Описание
    int Count { get; }
    Количество элементов коллекции в данный момент bool IsSynchronized
    { get; }
    Принимает значение true
    , если коллекция синхронизирована, и значение false в противном случае По умолчанию коллекции не синхронизированы Но для большинства коллекций можно получить синхронизированную версию object SyncRoot
    { get; }
    Объект, для которого коллекция может быть синхронизирована
    Свойство
    Count
    — самое востребованное, поскольку содержит количество элементов, хранимых в коллекции в данный момент. Если свойство
    Count равно нулю, значит, коллекция пуста. В интерфейсе
    ICollection определен следующий метод: void CopyTo(Array
    target
    , int
    startIdx
    )
    Метод
    CopyTo()
    копирует содержимое коллекции в массив, заданный параметром
    target
    , начиная с индекса, заданного параметром
    startIdx
    . Можно сказать, что метод
    CopyTo()
    обеспечивает переход от коллекции к стандартному C#-массиву.
    Поскольку интерфейс
    ICollection наследует интерфейс
    IEnumerable
    , он также включает его единственный метод
    GetEnumerator()
    :
    IEnumerator GetEnumerator()
    Этот метод возвращает нумератор коллекции.
    Таблица 22.1. Интерфейсы коллекций
    Интерфейс
    Описание
    ICollection
    Определяет элементы, которые должны иметь все коллекции
    IEnumerable
    Определяет метод
    GetEnumerator()
    , который поддерживает нумератор для любого класса коллекции
    IEnumerator
    Содержит методы, которые позволяют поэлементно получать содержимое коллекции
    IList
    Определяет коллекцию, к которой можно получить доступ посредством индексатора
    IDictionary
    Определяет коллекцию, которая состоит из пар ключ/значение

    Глава 22. Работа с коллекциями
    613
    Окончание табл. 22.1
    Интерфейс
    Описание
    IDictionaryEnumerator
    Определяет нумератор для коллекции, которая реализует интерфейс
    IDictionary
    IComparer
    Определяет метод
    Compare()
    , который выполняет сравнение объектов, хранимых в коллекции
    IHashCodeProvider
    Определяет хеш-функцию
    Интерфейс IList
    Интерфейс
    IList наследует интерфейс
    ICollection и определяет поведение коллекции, доступ к элементам которой разрешен посредством индекса с отсчетом от нуля.
    Помимо методов, определенных в интерфейсе
    ICollection
    , интерфейс
    IList определяет и собственные методы (они сведены в табл. 22.2). Некоторые из этих методов служат для модификации коллекции. Если же коллекция предназначена только для чтения или имеет фиксированный размер, вызов этих методов приведет к генерированию исключения типа
    NotSupportedException
    Таблица 22.2. Методы, определенные в интерфейсе IList
    Метод
    Описание
    int Add( object
    obj
    )
    Добавляет объект
    obj
    в вызывающую коллекцию. Возвращает индекс, по которому этот объект сохранен void Clear()
    Удаляет все элементы из вызывающей коллекции bool Contains( object
    obj
    )
    Возвращает значение true
    , если вызывающая коллекция содержит объект, переданный в параметре
    obj
    , и значение false в противном случае int IndexOf( object
    obj
    )
    Возвращает индекс объекта
    obj
    , если он (объект) содержится в вызывающей коллекции. Если объект
    obj
    не обнаружен, метод возвращает -1 void Insert( int idx, object
    obj
    )
    Вставляет е вызывающую коллекцию объект
    obj
    по индексу, заданному параметром
    idx
    . Элементы, находившиеся до этого по индексу
    idx
    и далее, смещаются вперед, чтобы освободить место для вставляемого объекта
    obj
    void Remove( object
    obj
    )
    Удаляет первое вхождение объекта
    obj
    из вызывающей коллекции. Элементы, находившиеся до этого за удаленным элементом, смещаются назад, чтобы ликвидировать образовавшуюся "брешь” void RemoveAt( int
    idx
    )
    Удаляет из вызывающей коллекции объект, расположенный по индексу, заданному параметром
    idx
    . Элементы, находившиеся до этого за удаленным элементом, смешаются назад, чтобы ликвидировать образовавшуюся "брешь"
    Объекты добавляются в коллекцию типа
    IList посредством вызова метода
    Add()
    Обратите внимание на то, что метод
    Add()
    принимает аргументы типа object
    . Поскольку класс object является базовым для всех типов, в коллекции можно сохранить объект любого типа. Это справедливо и для типов значений (нессылочных типов), поскольку здесь автоматически выполняется приведение к объектному типу (
    boxing
    ).
    Удалить объект из коллекции можно с помощью метода
    Remove()
    или
    RemoveAt()
    . Метод
    Remove()
    удаляет заданный объект, а метод
    RemoveAt()
    — объект, расположенный по заданному индексу. Для полной очистки коллекции достаточно вызвать метод
    Clear()

    614
    Часть II. Библиотека C#
    Чтобы узнать, содержит ли коллекция заданный объект, вызовите метод
    Contains()
    . Получить индекс заданного объекта поможет метод
    IndexOf()
    , а вставить элемент по заданному индексу — метод
    Insert()
    В классе
    IList определены следующие свойства: bool IsFixedSize { get; } bool IsReadOnly { get; }
    Если коллекция имеет фиксированный размер, свойство
    IsFixedSize принимает значение true
    . Это означает, что в такую коллекцию нельзя вставлять элементы и удалять их из нее. Если коллекция предназначена только для чтения, свойство
    IsReadOnly имеет значение true. Это говорит о том, что содержимое коллекции изменению не подлежит.
    В классе
    IList определен следующий индексатор: object this[int
    idx
    ] { get; set; }
    Этот индексатор можно использовать для считывания или записи значения нужного элемента. Но его нельзя применить для добавления в коллекцию нового элемента. Для этой цели существует метод
    Add()
    . Но после того как элемент добавлен в коллекцию, к нему можно получить доступ с помощью индексатора.
    Интерфейс IDictionary
    Интерфейс
    IDictionary определяет поведение коллекции, которая устанавливает соответствие между уникальными ключами и значениями. Ключ — это объект, который используется для получения соответствующего ему значения. Следовательно, коллекция, которая реализует интерфейс
    IDictionary
    , служит для хранения пар ключ/значение.
    Сохраненную однажды пару можно затем извлечь по заданному ключу. Интерфейс
    IDictionary наследует интерфейс
    ICollection
    . Методы, объявленные в интерфейсе
    IDictionary
    , сведены в табл. 22.3. Некоторые из них при попытке задать нулевой ключ генерируют исключение типа
    NotSupportedException
    Таблица 22.3. Методы, определенные в интерфейсе IDictionary
    Метод
    Описание
    void Add( object
    k
    , object
    v
    )
    Добавляет в вызывающую коллекцию пару ключ/значение, заданную параметрами
    k
    и
    v
    . Ключ
    k
    не должен быть нулевым.
    Если окажется, что ключ
    k
    уже хранится в коллекции, генерируется исключение типа
    ArgumentException void Clear()
    Удаляет все пары ключ/значение из вызывающей коллекции bool Contains( object
    k
    )
    Возвращает значение true
    , если вызывающая коллекция содержит объект
    k
    в качестве ключа. В противном случае возвращает значение false
    IDictionaryEnumerator
    GetEnumerator()
    Возвращает нумератор для вызывающей коллекции void Remove( object
    k
    )
    Удаляет элемент, ключ которого равен значению
    k
    Чтобы добавить пару ключ/значение в
    IDictionary
    -коллекцию, используйте метод
    Add()
    . Обратите внимание на то, что ключ и его значение задаются как отдельные параметры. Чтобы удалить из коллекции-словаря ненужный элемент, необходимо передать методу
    Remove()
    соответствующий ему ключ. Для очистки всей коллекции используется метод
    Clear()

    Глава 22. Работа с коллекциями
    615
    Чтобы определить, содержит ли коллекция заданный объект, достаточно вызвать метод
    Contains()
    , передав ему ключ интересующего вас объекта. Метод
    GetEnumerator()
    возвращает нумератор, совместимый с коллекцией
    IDictionary
    Этот нумератор работает в "парном" (ключ/значение) режиме.
    В интерфейсе
    IDictionary определены следующие свойства:
    Свойство
    Описание
    bool IsFixedSize { get; }
    Равно значению true
    , если словарь имеет фиксированный размер bool IsReadOnly { get; }
    Равно значению true
    , если словарь предназначен только для чтения
    ICollection Keys { get; }
    Получает коллекцию ключей
    ICollection Values { get; }
    Получает коллекцию значений
    Обратите внимание на то, что с помощью свойств
    Keys и
    Values ключи и значения, хранимые в словарной коллекции, можно получить в виде отдельных списков. В интерфейсе
    IDictionary определен следующий индексатор: object this[object key] { get; set; }
    Этот индексатор можно использовать для получения или установки значения элемента. Его можно также использовать для добавления в коллекцию нового элемента.
    Обратите внимание на то, что “индекс” в данном случае не является обычным индексом, а ключом элемента.
    Интерфейсы IEnumerable, IEnumerator и IDictionaryEnumerator
    Интерфейс
    IEnumerable должен быть реализован в любом классе, если в нем предполагается поддержка нумераторов. Как упоминалось выше, все классы коллекций реализуют интерфейс
    IEnumerable
    , поскольку он наследуется интерфейсом
    ICollection
    . В интерфейсе
    IEnumerable определен единственный метод с именем
    GetEnumerator()
    :
    IEnumerator GetEnumerator()
    Он возвращает нумератор для коллекции. Кроме того, реализация интерфейса
    IEnumerable позволяет получить доступ к содержимому коллекции с помощью цикла fоreach
    Интерфейс
    IEnumerator
    , собственно, и определяет действие любого нумератора.
    Используя его методы, можно циклически опросить содержимое коллекции. Для коллекций, в которых хранятся пары ключ/значение (т.е. словари), метод
    GetEnumerator()
    возвращает объект типа
    IDictionaryEnumerator
    , а не типа
    IEnumerator
    . Класс
    IDictionaryEnumerator является производным от класса
    IEnumerator и распространяет свои функциональные возможности нумератора на область словарей.
    Методы, определенные в интерфейсе
    IEnumerator
    , рассматриваются ниже в этой главе.
    Интерфейс IComparer
    В интерфейсе
    IComparer определен метод
    Compare()
    , который позволяет сравнивать два объекта: int Compare(object
    v1
    , object
    v2
    )

    616
    Часть II. Библиотека C#
    Метод
    Compare()
    возвращает положительное число, если значение
    v1
    больше значения
    v2
    , отрицательное, если
    v1
    меньше
    v2
    , и нуль, если сравниваемые значения равны. Этот интерфейс можно использовать для задания способа сортировки элементов коллекции.
    Интерфейс IHashCodeProvider
    Интерфейс
    IHashCodeProvider должен быть реализован коллекцией, если программисту необходимо определить собственную версию метода
    GetHashCode()
    Вспомните, что все объекты (для получения хеш-кода) наследуют метод
    Object.GetHashCode()
    , который используется по умолчанию. Посредством реализации интерфейса
    IHashCodeProvider можно определить альтернативный метод.
    Структура DictionaryEntry
    В пространстве имен
    System.Collections определен тип структуры с именем
    DictionaryEntry
    . Коллекции, в которых хранятся пары ключ/значение, используют для их хранения объект типа
    DictionaryEntry
    . В этой структуре определены следующие два свойства: public object Key { get; set; } public object Value { get; set; }
    Эти свойства используются для получения доступа к ключу или к соответствующему ему значению. Объект типа
    DictionaryEntry можно создать с помощью следующего конструктора: public DictionaryEntry(object
    k
    , object
    v
    )
    Здесь параметр
    k
    принимает ключ, а параметр
    v
    — значение.
    Классы коллекций общего назначения
    Теперь, когда вы познакомились с интерфейсами коллекций, можно переходить к рассмотрению стандартных классов, которые их реализуют. Как упоминалось выше, классы коллекций делятся на три основных категории: общего назначения, специализированные и ориентированные на побитовую организацию данных. Классы общего назначения можно использовать для хранения объектов любого типа. Битовые предназначены для хранения битовой информации. Коллекции специального назначения разрабатываются для обработки данных конкретного типа. Этот раздел посвящен классам коллекций общего назначения.
    Итак, перечислим классы коллекций общего назначения:
    Класс
    Описание
    ArrayList
    Динамический массив, т.е. массив который при необходимости может увеличивать свой размер
    Hashtable
    Хеш-таблица для пар ключ/значение
    Queue
    Очередь, или список, действующий по принципу: первым прибыл — первым обслужен
    SortedList
    Отсортированный список пар ключ/значение
    Stack
    Стек, или список, действующий по принципу: первым прибыл— последним обслужен
    В следующих разделах эти классы коллекций и возможности их использования рассматриваются более подробно.

    Глава 22. Работа с коллекциями
    617
    Класс ArrayList
    Класс
    ArrayList предназначен для поддержки динамических массивов, которые при необходимости могут увеличиваться или сокращаться. В C# стандартные массивы имеют фиксированную длину, которая не может измениться во время выполнения программы. Это означает, что программист должен знать заранее, сколько элементов будет храниться в массиве. Но иногда до выполнения программы нельзя точно сказать, массив какого размера понадобится. В таких случаях и используется класс
    ArrayList
    . Объект класса
    ArrayList представляет собой массив переменной длины, элементами которого являются объектные ссылки. Любой объект класса
    ArrayList создается с некоторым начальным размером. При превышении этого размера коллекция автоматически его увеличивает. В случае удаления объектов массив можно сократить. Коллекция класса
    ArrayList
    , пожалуй, наиболее употребимая, поэтому ее стоит рассмотреть в деталях.
    Класс
    ArrayList реализует интерфейсы
    ICollection
    ,
    IList
    ,
    IEnumerable и
    ICloneable
    . В классе
    ArrayList определены следующие конструкторы: public ArrayList() public ArrayList(ICollection
    с
    ) public ArrayList(int
    capacity
    )
    Первый конструктор предназначен для создания пустого
    ArrayList
    -массива с начальной емкостью, равной 16 элементам. Второй служит для построения массива, который инициализируется элементами и емкостью коллекции, заданной параметром
    с
    Третий конструктор создает список с заданной начальной емкостью. Емкость (или вместимость) — это размер массива для хранения элементов. При добавлении элементов в
    ArrayList
    -массив его емкость автоматически увеличивается, причем каждый раз, когда список должен расшириться, его емкость удваивается.
    Помимо методов, определенных в интерфейсах, которые реализует класс
    ArrayList
    , в нем определены и собственные методы. Наиболее употребимые из них перечислены в табл. 22.4. Коллекцию класса
    ArrayList можно отсортировать с помощью метода
    Sort()
    . В отсортированной коллекции можно эффективно выполнять поиск элементов, используя метод
    BinarySearch()
    . При необходимости содержимое
    ArrayList
    -коллекции можно реверсировать, вызвав метод
    Reverse()
    Класс
    ArrayList поддерживает ряд методов, которые действуют в некотором диапазоне элементов коллекции. Например, вызвав метод
    InsertRange()
    , можно вставить в
    ArrayList
    -массив другую коллекцию. С помощью метода
    RemoveRange()
    можно удалить из коллекции заданный диапазон элементов. А если нужно заменить элементы заданного диапазона одной коллекции элементами другой, используйте метод
    SetRange()
    . Сортировать можно не только всю коллекцию, но и заданный диапазон внутри нее. То же справедливо и для поиска.
    По умолчанию коллекция класса
    ArrayList не синхронизирована. Чтобы поместить коллекцию в синхронизированную оболочку, вызовите метод
    Synchronized()
    Таблица 22.4. Наиболее употребимые методы класса ArrayList
    1   ...   37   38   39   40   41   42   43   44   ...   52


    написать администратору сайта