Программирование >>  Программирование с использованием ajax 

1 ... 110 111 112 [ 113 ] 114 115 116 ... 396


гому. На привыкание к применению таких обобщенных типов делегатов для сортировки и поиска в обобщенных коллекциях может потребоваться некоторое время, но при таком подходе код получается более простым и эффективным с очень логичной структурой. Поэтому потратить время на изучения описанных в этом разделе приемов очень даже стоит.

Тип Dictionary<K, V>

Тип Dictionary<K, V> позволяет определять коллекцию пар ключ-значение\ В отличие от других обобщенных типов-коллекций, о которых рассказывалось в этой главе, данный класс требует создания экземпляров двух типов: одного для того ключа и одного для значения, представляющего каждый элемент в коллекции.

После создания экземпляра объекта Dictionary<K, V> в нем можно выполнять во многом все те же операции, что и в любом классе, который наследуется от DictionaryBase, но только с помощью безопасным к типам методов и свойств. Можно, например, добавлять пары ключей и значений с помощью строго типизированного метода Add ():

Dictionary<string, int> things = new Dictionary<string, int>();

things.Add( Green Things , 29);

things.Add( Blue Things , 94);

things.Add( Yellow Things , 34);

things.Add( Red Things , 52);

things.Add( Brown Things , 27);

Можно проходить по ключам и значениям в коллекции с помощью свойств Keys и Values:

foreach (string key in things.Keys) {

Console.WriteLine(key) ;

foreach (int value in things.Values) {

Console.WriteLine(value);

Помимо этого по элементам в коллекции еще можно проходить и получением каждого из них в виде экземпляра KeyValuePair<K, V>, во многом подобно тому, как это можно делать с объектами DictionaryEntry, которые демонстрировались в предыдущей главе:

foreach (KeyValuePair<string, int> thing in things) {

Console.WriteLine ( {0} = {1} , thing.Key, thing.Value);

О Dictionary<K, V> важно запомнить одну вещь: ключ для каждого элемента должен обязательно быть уникальным. Попытки добавить элемент с ключом, идентичным ключу уже добавленного элемента, будут приводить к генерации исключения ArgumentException. Из-за этого Dictionary<K, V> позволяет передавать своему конструктору в качестве аргумента интерфейс IComparer<K>. Подобное может быть необходимо в случае использования в качестве ключей своих собственных классов, которые не поддерживают ни интерфейса IComparable, ни интерфейса IComparable<K>, или при желании сделать так, чтобы объекты сравнивались посредством какого-то нестандартного процесса.



Например, в приведенном выше коде для сравнения строковых ключей можно было бы использовать метод, не учитывающий регистр:

Dictionary<string, int> things =

new Dictionary<string, int>(StringComparer.CurrentCulturelgnoreCase);

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

things.Add( Green Things , 29); things.Add( Green things , 94);

Еще конструктору Dictionary<K, V> можно также передавать начальную вместимость (с помощью int) и набор элементов (с помощью интерфейса IDictionary<K, V>)

Изменение проекта CardLib для использования обобщенной коллекции

Теперь в проект CardLib, который разрабатывался на протяжения нескольких последних глав, можно внести одно простое изменение, заключающееся в модификации класса Cards таким образом, чтобы в нем использовался обобщенный класс коллекции, и тем самым сократить количество требуемых строк кода. Необходимое изменение, внести которое нужно в определение класса Cards, выглядит следующим образом:

public class Cards : List<Card>, ICloneable

Еще можно удалить все методы класса Cards, кроме Clone (), который требуется для ICloneable, и метода СоруТо (), потому что версия СоруТо (), которую предоставляет List<Card>, работает с массивом объектов Card, а не коллекцией Cards. В метод Clone () необходимо внести одну небольшую модификацию, поскольку в классе List<T> не определено свойство List, которое должно использоваться:

public object Clone О {

Cards newCards = new Cards (); foreach (Card sourceCard in this)

newCards.Add(sourceCard.Clone 0 as Card);

return newCards;

Полный код можно найти в загружаемом коде для этой главы (в проекте

Chl2CardLib).

Определение обобщений

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

□ обобщенных классов;

□ обобщенных интерфейсов;

□ обобщенных методов;

□ обобщенных делегатов.



Здесь будут рассмотрены следующие усовершенствованные приемы для решения проблем, встречающихся при определении обобщенных типов:

□ использование ключевого слова default;

□ ограничение типов;

□ наследование от обобщенных классов;

□ применение обобщенных операций.

Определение обобщенных классов

Для создания обобщенного класса достаточно применить в определении класса синтаксис в виде угловых скобок:

class MyGenericClass<T>

Здесь на месте Т можно указывать какой угодно идентификатор, главное соблюдать стандартные правила именования языка С#, т.е. не начинать имя с числа и т.п. Обычно, однако, достаточно использовать и просто Т. Обобщенный класс может содержать в своем определении любое количество типов, отделенных друг от друга запятой:

class MyGenericClass<Tl, Т2, Т3>

После определения эти типы можно применять в определении класса точно так же, как и любые другие типы. Например, их можно использовать и в качестве типов для переменных членов, и в качестве возвращаемых типов для членов, вроде свойств или методов, и в качестве типов параметров для аргументов методов:

class MyGenericClass<Tl, Т2, Т3> {

private Т1 innerTlObject; public MyGenericClass (Tl item) {

innerTlObject = item;

public Tl InnerTlObject {

get {

return innerTlObject;

Здесь объект типа Tl может передаваться конструктору, и к нему разрешено получать доступ только для чтения через свойство InnerTlObject. Обратите внимание, что практически никаких предположений касательно того, какими являются предоставляемые классу типы, делать нельзя. Следующий код, например, компилироваться не будет:



1 ... 110 111 112 [ 113 ] 114 115 116 ... 396

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика