Выбрать главу
ты вызывающей коллекции в обратном порядке public void Reverse(int index, int count) Располагает в обратном порядке часть вызываю щей коллекции, начиная с элемента, указываемого по индексу index, и включая количество элемен тов, определяемое параметром count public void Sort() Сортирует вызывающую коллекцию по нарас тающей В классе List определяется также собственное свойство Capacity, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Это свойство объявля ется следующим образом. public int Capacity { get; set; } Свойство Capacity позволяет установить и получить емкость вызывающей коллек ции в качестве динамического массива. Эта емкость равна количеству элементов, кото рые может содержать коллекция до ее вынужденного расширения. Такая коллекция расширяется автоматически, и поэтому задавать ее емкость вручную необязательно. Но из соображений эффективности это иногда можно сделать, если заранее известно количество элементов коллекции. Благодаря этому исключаются издержки на выделе ние дополнительной памяти. В классе List реализуется также приведенный ниже индексатор, определен ный в интерфейсе IList. public Т this[int index] { get; set; } С помощью этого индексатора устанавливается и получается значение элемента коллекции, указываемое по индексу index. В приведенном ниже примере программы демонстрируется применение клас са List. Это измененный вариант примера, демонстрировавшего ранее класс ArrayList. Единственное изменение, которое потребовалось для этого, заключалось в замене класса ArrayList классом List, а также в использовании параметров обоб щенного типа. Окончание табл. 25.15 Метод Описание public void Sort(IСоmраrеr<Т> comparer) Сортирует вызывающую коллекцию, используя для сравнения способ, задаваемый параметром comparer. Если параметр comparer имеет пустое значение, то для сравнения используется способ, выбираемый по умолчанию public void Sort(Comparison comparison) Сортирует вызывающую коллекцию, используя для сравнения указанный делегат public void Sort (int index, int count, IComparer comparer) Сортирует вызывающую коллекцию, используя для сравнения способ, задаваемый параметром comparer. Сортировка начинается с элемента, ука зываемого по индексу index, и включает количе ство элементов, определяемых параметром count. Если параметр comparer имеет пустое значение, то для сравнения используется способ, выбираемый по умолчанию public T[] ToArray() Возвращает массив, содержащий копии элементов вызывающего объекта public void TrimExcess() Сокращает емкость вызывающей коллекции таким образом, чтобы она не превышала 10% от количе ства элементов, хранящихся в ней на данный момент // Продемонстрировать применение класса List. using System; using System.Collections.Generic; class GenListDemo { static void Main() { // Создать коллекцию в виде динамического массива. List lst = new List(); Console.WriteLine("Исходное количество элементов: " + lst.Count); Console.WriteLine(); Console.WriteLine("Добавить 6 элементов"); // Добавить элементы в динамический массив. lst.Add('С'); lst.Add('А'); lst.Add('Е'); lst.Add('В'); lst.Add('D'); lst.Add('F'); Console.WriteLine("Количество элементов: " + lst.Count); // Отобразить содержимое динамического массива, // используя индексирование массива. Console.Write("Текущее содержимое: "); for (int i=0; i < lst.Count; i++) Console.Write(lst[i] + " "); Console.WriteLine("\n"); Console.WriteLine("Удалить 2 элемента "); // Удалить элементы из динамического массива. lst.Remove('F'); lst.Remove('А'); Console.WriteLine("Количество элементов: " + lst.Count); // Отобразить содержимое динамического массива, используя цикл foreach. Console.Write("Содержимое: "); foreach(char с in lst) Console.Write(с + " "); Console.WriteLine("\n"); Console.WriteLine("Добавить еще 20 элементов"); // Добавить количество элементов, достаточное для // принудительного расширения массива. for(int i=0; i < 20; i++) lst.Add((char)('a' + i)); Console.WriteLine("Текущая емкость: " + lst.Capacity); Console.WriteLine("Количество элементов после добавления 20 новых: " + lst.Count); Console.Write("Содержимое: "); foreach(char с in lst) Console.Write(с + " "); Console.WriteLine("\n"); // Изменить содержимое динамического массива, // используя индексирование массива. Console.WriteLine("Изменить три первых элемента"); lst[0] = 'X'; lst [1] = 'Y'; lst[2] = 'Z'; Console.Write("Содержимое: "); foreach(char с in lst) Console.Write(с + " "); Console.WriteLine(); // Следующая строка кода недопустима из-за // нарушения безопасности обобщенного типа. // lst.Add(99); // Ошибка, поскольку это не тип char! } } Эта версия программы дает такой же результат, как и предыдущая. Исходное количество элементов: 0 Добавить 6 элементов Количество элементов: 6 Текущее содержимое: С А Е В D F Удалить 2 элемента Количество элементов: 4 Содержимое: С Е В D Добавить еще 20 элементов Текущая емкость: 32 Количество элементов после добавления 20 новых: 24 Содержимое: C E B D a b c d e f g h i j k l m n o p q r s t Изменить три первых элемента Содержимое: X Y Z D a b c d e f g h i j k l m n o p q r s t Класс LinkedList В классе LinkedList создается коллекция в виде обобщенного двунаправлен ного списка. В этом классе реализуются интерфейсы ICollection, ICollection, IEnumerable, IEnumerable, ISerializable и IDeserializationCallback. В двух последних интерфейсах поддерживается сериализация списка. В классе LinkedList определяются два приведенных ниже открытых конструктора. public LinkedList() public LinkedList(IEnumerable collection) В первом конструкторе создается пустой связный список, а во втором конструкто ре — список, инициализируемый элементами из коллекции collection. Как и в большинстве других реализаций связных списков, в классе LinkedList инкапсулируются значения, хранящиеся в узлах списка, где находятся также ссылки на предыдущие и последующие элементы списка. Эти узлы представляют собой объекты класса LinkedListNode. В классе LinkedListNode предоставляются четыре следующих свойства. public LinkedListNode Next { get; } public LinkedListNode Previous { get; } public LinkedList List { get; } public T Value { get; set; } С помощью свойств Next и Previous получаются ссылки на предыдущий и после дующий узлы списка соответственно, что дает возможность обходить список в обоих направлениях. Если же предыдущий или последующий узел отсутствует, то возвра щается пустая ссылка. Для получения ссылки на сам список служит свойство List. А с помощью свойства Value можно устанавливать и получать значение, находящееся в узле списка. В классе LinkedList определяется немало методов. В табл. 25.16 приве дены наиболее часто используемые методы данного класса. Кроме того, в клас се LinkedList определяются собственные свойства, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Эти свойства приведены ниже. public LinkedListNode First { get; } public LinkedListNode Last { get; } С помощью свойства First получается первый узел в списке, а с помощью свой ства Last — последний узел в списке. Таблица 25.16. Наиболее часто используемые методы, определенные в классе LinkedList Метод Описание public LinkedListNode AddAfter(LinkedListNode node, T value) Добавляет в список узел со значением value не посредственно после указанного узла node. Указы ваемый узел node не должен быть пустым (null). Метод возвращает ссылку на узел, содержащий зна чение value public void AddAfter(LinkedListNode node, LinkedListNode newNode) Добавляет в список новый узел newNode непо средственно после указанного узла node. Ука зываемый узел node не должен быть пустым (null). Если узел node отсутствует в списке или если новый узел newNode является частью другого списка, то генерируется исключение InvalidOperationException public LinkedListNode AddBefore(LinkedListNode node, T value) Добавляет в список узел со значением value непо средственно перед указанным узлом node. Указы ваемый узел node не должен быть пустым (null). Метод возвращает ссылку на узел, содержащий зна чение value В приведенном ниже примере программы демонстрируется применение класса LinkedList. // Продемонстрировать применение класса LinkedList. using System; using System.Collections.Generic; Окончание табл. 25.16 Метод Описание public void AddBefore(LinkedListNode node, LinkedListNode newNode) Добавляет в список новый узел newNode не посредственно перед указанным узлом node. Указываемый узел node не должен быть пу стым (null). Если узел node отсутствует в спи ске или если новый узел newNode является ча стью другого списка, то генерируется исключение InvalidOperationException public LinkedList AddFirst(T value) Добавляет узел со значением value в начало спи ска. Метод возвращает ссылку на узел, содержащий значение value public void AddFirst(LinkedListNode node) Добавляет узел node в начало списка. Если узел node является частью другого списка, то генериру ется исключение InvalidOperationException public LinkedList AddLast(T value) Добавляет узел со значением value в конец спи ска. Метод возвращает ссылку на узел, содержащий значение value public void AddLast(LinkedListNode node) Добавляет узел node в конец списка. Если узел node является частью другого списка, то генериру ется исключение InvalidOperationException public LinkedList Find(T value) Возвращает ссылку на первый узел в списке, име ющий значение value. Если искомое значение value отсутствует в списке, то возвращается пустое значение public LinkedList FindLast(T value) Возвращает ссылку на последний узел в списке, имеющий значение value. Если искомое значение value отсутствует в списке, то возвращается пустое значение public bool Remove(T value) Удаляет из списка первый узел, содержащий значе ние value. Возвращает логическое значение true, если узел удален, т.е. если узел со значением value обнаружен в списке и удален; в противном случае возвращает логическое значение false public void Remove(LinkedList node) Удаляет из списка узел, соответствующий ука занному узлу node. Если узел node отсут ствует в списке, то генерируется исключение InvalidOperationException public void RemoveFirst() Удаляет из списка первый узел public void RemoveLast() Удаляет из списка последний узел class GenLinkedListDemo { static void Main() { // Создать связный список. LinkedList ll = new LinkedList(); Console.WriteLine("Исходное количество элементов в списке: " + ll.Count) Console.WriteLine(); Console.WriteLine("Добавить в список 5 элементов"); // Добавить элементы в связный список. ll.AddFirst('А'); ll.AddFirst('В'); ll.AddFirst('С'); ll.AddFirst('D'); ll.AddFirst('Е'); Console.WriteLine("Количество элементов в списке: " + ll.Count); // Отобразить связный список, обойдя его вручную. LinkedListNode node; Console.Write("Отобразить содержимое списка по ссылкам: "); for(node = ll.First; node != null; node = node.Next) Console.Write(node.Value + " "); Console.WriteLine("\n"); // Отобразить связный список, обойдя его в цикле foreach. Console.Write("Отобразить содержимое списка в цикле foreach: "); foreach(char ch in 11) Console.Write(ch + " "); Console.WriteLine("\n"); // Отобразить связный список, обойдя его вручную в обратном направлении. Console.Write("Следовать по ссылкам в обратном направлении: "); for(node = ll.Last; node != null; node = node.Previous) Console.Write(node.Value + " "); Console.WriteLine("\n"); // Удалить из списка два элемента. Console.WriteLine("Удалить 2 элемента из списка"); // Удалить элементы из связного списка. ll.Remove('С'); ll.Remove('А'); Console.WriteLine("Количество элементов в списке: " + ll.Count); // Отобразить содержимое видоизмененного списка в цикле foreach. Console.Write("Содержимое списка после удаления элементов: "); foreach(char ch in ll) Console.Write(ch + " "); Console.WriteLine("\n"); // Добавить три элемента в конец списка. ll.AddLast('X'); ll.AddLast('Y'); ll.AddLast('Z'); Console.Write("Содержимое списка после ввода элементов: "); foreach(char ch in ll) Console.Write(ch + " "); Console.WriteLine("\n"); } } Ниже приведен результат выполнения этой программы. Исходное количество элементов в списке: 0 Добавить в список 5 элементов Количество элементов в списке: 5 Отобразить содержимое списка по ссылкам: Е D С В А Отобразить содержимое списка в цикле foreach: Е D С В А Следовать по ссылкам в обратном направлении: А В С D Е Удалить 2 элемента из списка Количество элементов в списке: 3 Содержимое списка после удаления элементов: Е D В Содержимое списка после ввода элементов: Е D В X Y Z Самое примечательное в этой программе — это обход списка в прямом и обрат ном направлении, следуя по ссылкам, предоставляемым свойствами Next и Previous. Двунаправленный характер подобных связных списков имеет особое значение для приложений, управляющих базами данных, где нередко требуется перемещаться по списку в обоих направлениях. Класс Dictionary Класс Dictionary позволяет хранить пары "ключ-значение" в коллекции как в словаре. Значения доступны в словаре по соответствующим клю чам. В этом отношении данный класс аналогичен необобщенному классу Hashtable. В классе Dictionary реализуются интерфейсы IDictionary, IDictionary, ICollection, ICollection>, IEnumerable, IEnumerable>, ISerializable и IDeserializationCallback. В двух последних интерфейсах поддер живается сериализация списка. Словари имеют динамический характер, расширяясь по мере необходимости. В классе Dictionary предоставляется немало конструкторов. Ниже перечислены наиболее часто используемые из них. public Dictionary() public Dictionary(IDictionary dictionary) public Dictionary(int capacity) В первом конструкторе создается пустой словарь с выбираемой по умолчанию первоначальной емкостью. Во втором конструкторе создается словарь с указанным ко личеством элементов dictionary. А в третьем конструкторе с помощью параметра сараcity указывается емкость коллекции, создаваемой в виде словаря. Если размер словаря заранее известен, то, указав емкость создаваемой коллекции, можно исклю чить изменение размера словаря во время выполнения, что, как правило, требует до полнительных затрат вычислительных ресурсов. В классе Dictionary определяется также ряд методов. Некото рые наиболее часто используемые методы этого класса сведены в табл. 25.17. Таблица 25.17. Наиболее часто используемые методы, определенные в классе Dictionary Метод Описание public void Add(TKey key, TValue value) Добавляет в словарь пару “ключ-значение”, определяемую параметрами key и value. Если ключ key уже находится в словаре, то его значение не изменяется, и генерируется ис ключение ArgumentException public bool ContainsKey(TKey key) Возвращает логическое значение true, если вызывающий словарь содержит объект key в качестве ключа; а иначе — логическое значе ние false public bool ContainsValue(TValue value) Возвращает логическое значение true, если вызывающий словарь содержит значение value; в противном случае — логическое зна чение false public bool Remove(TKey key) Удаляет ключ key из словаря. При удачном исходе операции возвращается логическое значение true, а если ключ key отсутствует в словаре — логическое значение false Кроме того, в классе Dictionary определяются собственные свойства, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Эти свойства приведены ниже. Свойство Описание public IEqualityComparer Comparer { get; } Получает метод сравнения для вызывающего словаря public Dictionary. KeyCollection Keys { get; } Получает коллекцию ключей public Dictionary. ValueCollection Values { get; } Получает коллекцию значений Следует иметь в виду, что ключи и значения, содержащиеся в коллекции, доступ ны отдельными списками с помощью свойств Keys и Values. В коллекциях типа Dictionary.KeyCollection и Dictionary. ValueCollection реализуются как обобщенные, так и необобщенные формы интер фейсов ICoirection и IEnumerable. И наконец, в классе Dictionary реализуется приведенный ниже индексатор, определенный в интерфейсе IDictionary. public TValue this[TKey key] { get; set; } Этот индексатор служит для получения и установки значения элемента коллекции, а также для добавления в коллекцию нового элемента. Но в качестве индекса в данном случае служит ключ элемента, а не сам индекс. При перечислении коллекции типа Dictionary из нее возвра щаются пары "ключ-значение" в форме структуры KeyValuePair. Напомним, что в этой структуре определяются два поля. public TKey Key; public TValue Value; В этих полях содержится ключ или значение соответствующего элемента коллек ции. Как правило, структура KeyValuePair не используется не посредственно, поскольку средства класса Dictionary позволяют работать с ключами и значениями по отдельности. Но при перечислении коллекции типа Dictionary, например, в цикле foreach перечисляемыми объектами являются пары типа KeyValuePair. Все ключи в коллекции типа Dictionary должны быть уни кальными, причем ключ не должен изменяться до тех пор, пока он служит в качестве ключа. В то же время значения не обязательно должны быть уникальными. К тому же объекты не хранятся в коллекции типа Dictionary в отсортирован ном порядке. В приведенном ниже примере демонстрируется применение класса Dictionary. // Продемонстрировать применение класса обобщенной // коллекции Dictionary. using System; using System.Collections.Generic; class GenDictionaryDemo { static void Main() { // Создать словарь для хранения имен и фамилий // работников и их зарплаты. Dictionary dict = new Dictionary(); // Добавить элементы в коллекцию. diet.Add("Батлер, Джон", 73000); diet.Add("Шварц, Capa", 59000); diet.Add("Пайк, Томас", 45000); diet.Add("Фрэнк, Эд", 99000); // Получить коллекцию ключей, т.е. фамилий и имен. ICollection с = diet.Keys; // Использовать ключи для получения значений, т.е. зарплаты. foreach(string str in с) Console.WriteLine("{0}, зарплата: {1:C}", str, diet[str]); } } Ниже приведен результат выполнения этой программы. Батлер, Джон, зарплата: $73,000.00 Шварц, Сара, зарплата: $59,000.00 Пайк, Томас, зарплата: $45,000.00 Фрэнк, Эд, зарплата: $99,000.00 Класс SortedDictionary В коллекции класса SortedDictionary пары "ключ-значение" хранятся таким же образом, как и в коллекции класса Dictionary, за исключением того, что они отсортированы по соответствующему ключу. В клас се SortedDictionary реализуются интерфейсы IDictionary, IDictionary, ICollection, ICollection>, IEnumerable и IEnumerable>. В классе SortedDictionary предоставляются также следующие конструкторы. public SortedDictionary() public SortedDictionary(IDictionary dictionary) public SortedDictionary(IComparer comparer) public SortedDictionary(IDictionary dictionary, IComparer comparer) В первом конструкторе создается пустой словарь, во втором конструкторе — сло варь с указанным количеством элементов dictionary. В третьем конструкторе допу скается указывать с помощью параметра comparer типа IComparer способ сравне ния, используемый для сортировки, а в четвертом конструкторе — инициализировать словарь, помимо указания способа сравнения. В классе SortedDictionary определен ряд методов. Некоторые наиболее часто используемые методы этого класса сведены в табл. 25.18. Таблица 25.18. Наиболее часто используемые методы, определенные в классе SortedDictionary Метод Описание public void Add(TKey key, TValue value) Добавляет в словарь пару "ключ-значение”, определяемую параметрами key и value. Если ключ key уже находится в словаре, то его значе ние не изменяется, и генерируется исключение ArgumentException public bool ContainsKey(TKey key) Возвращает логическое значение true, если вызыва ющий словарь содержит объект key в качестве клю ча; в противном случае — логическое значение false Метод Описание public bool ContainsValue(TValue value) Возвращает логическое значение true, если вызы вающий словарь содержит значение value; в про тивном случае — логическое значение false public bool Remove(TKey key) Удаляет ключ key из словаря. При удачном исходе операции возвращается логическое значение true, а если ключ key отсутствует в словаре — логическое значение false Кроме того, в классе SortedDictionary определяются собствен ные свойства, помимо тех, что уже объявлены в интерфейсах, которые в нем реализу ются. Эти свойства приведены ниже. Следует иметь в виду, что ключи и значения, содержащиеся в коллекции, доступ ны отдельными списками с помощью свойств Keys и Values. В коллекциях типа SortedDictionary.KeyCollection и SortedDictionary.ValueCollection реализуются как обобщенные, так и необобщенные фор мы интерфейсов ICollection и IEnumerable. И наконец, в классе SortedDictionary реализуется приведен ный ниже индексатор, определенный в интерфейсе IDictionary. public TValue this[TKey key] { get; set; } Этот индексатор служит для получения и установки значения элемента коллекции, а также для добавления в коллекцию нового элемента. Но в данном случае в качестве индекса служит ключ элемента, а не сам индекс. При перечислении коллекции типа SortedDictionary из нее возвращаются пары "ключ-значение" в форме структуры KeyValuePair. Напомним, что в этой структуре определяются два следующих поля. public TKey Key; public TValue Value; В этих полях содержится ключ или значение соответствующего элемента коллек ции. Как правило, структура KeyValuePair не используется не посредственно, поскольку средства класса SortedDictionary по зволяют работать с ключами и значениями по отдельности. Но при перечислении коллекции типа SortedDictionary, например в цикле foreach, перечисляемыми объектами являются пары типа KeyValuePair. Окончание табл. 25.18 Свойство Описание public Icomparer Comparer { get; } Получает метод сравнения для вызы вающего словаря public SortedDictionary. KeyCollection Keys { get; } Получает коллекцию ключей public SortedDictionary. ValueCollection Values { get; } Получает коллекцию значений Все ключи в коллекции типа SortedDictionary должны быть уникальными, причем ключ не должен изменяться до тех пор, пока он служит в каче стве ключа. В то же время значения не обязательно должны быть уникальными. В приведенном ниже примере демонстрируется применение класса SortedDicti