ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3217

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

p r i v a t e

s t r i n g n a m e ;

 

p u b l i c

S t u d e n t ( s t r i n g

name)

{

 

 

t h i s . n a m e = n a m e ;

 

}

 

 

p u b l i c

s t r i n g Name

 

{

 

 

g e t { r e t u r n n a m e ;

}

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

Обобщенные классы

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

Обобщенные классы безопасны

Когда вы объявляете массив, вы должны указать точный тип данных, которые могут в нем храниться. Если это i n t — то массив не может хранить ничего, кроме i n t или других числовых типов, которые С# в состоянии неявно преоб­ разовать в i n t . Если вы попытаетесь поместить в массив данные неверного типа, то получите от компилятора сообщение об ошибке. Таким образом ком­ пилятор обеспечивает безопасность типов, т.е. вы обнаруживаете и исправляе­ те проблему еще до того, как она проявится. Гораздо лучше получить сообще­ ние об ошибке от компилятора, чем в процессе работы программы.

Необобщенные коллекции небезопасны. В С# переменная любого типа ЯВЛЯ­ ЕТСЯ O b j e c t , поскольку класс O b j e c t является базовым классом для всех других типов, как типов-значений, так и типов-ссылок (см. раздел об унифика­ ции типов в главе 14, "Интерфейсы и структуры"). Однако когда вы сохраняете

типы-значения (числа, b o o l , s t r u c t ) в

коллекции, они должны быть упако­

ваны при помещении в нее

и распакованы

при извлечении из нее (см. оконча­

ние главы 14, "Интерфейсы

и структуры").

Первое следствие небезопасности необобщенных классов заключается в том, что вам требуется приведение типов (как показано в следующем фрагменте исходного текста) для получения исходного объекта из A r r a y L i s t , так как этот тип скрыт при упаковке.

ArrayList a L i s t

=

new A r r a y L i s t () ;

 

// Добавляем п я т ь - ш е с т ь э л е м е н т о в ,

а з а т е м . . .

string m y S t r i n g

=

( s t r i n g ) a L i s t [4] ;

// п р е о б р а з у е м в s t r i n g

Глава

15. Обобщенное программирование

343


Второе следствие в том, что в A r r a y L i s t одновременно могут храниться объекты разных типов. То есть вы можете написать, например, такой исход ный текст:

A r r a y L i s t a L i s t = new

A r r a y L i s t О ;

 

a L i s t . A d d ( " a s t r i n g " ) ; / / s t r i n g

- - O K

a L i s t . A d d ( 3 ) ;

/ /

i n t

- - O K

a L i s t . A d d ( a S t u d e n t ) ;

/ /

S t u d e n t - - O K

Однако если вы поместите в A r r a y L i s t (или другую необобщенную коллекции объекты разных несовместимых типов, то как вы потом сможете узнать тип, например третьего элемента? Если это S t u d e n t , а вы попытаетесь преобразовать его в string то получите ошибку времени выполнения программы.

Для безопасности следует производить проверку с использованием оператор is (рассматривавшегося в главе 12, "Наследование") или альтернативного я ратора as следующим образом:

i f ( a L i s t [ i ]

i s S t u d e n t )

//

Объект -

S t u d e n t ?

{

 

 

 

 

 

S t u d e n t a S t u d e n t = ( S t u d e n t ) a L i s t [ i ] ; / / Д а

 

 

 

/ / или . . .

 

 

 

S t u d e n t a S t u d e n t =

a L i s t [ i ] a s S t u d e n t ;

/ /

Получаем

S t u d e n t

i f ( a S t u d e n t

! = n u l l )

 

/ /

Невозможно, " a s "

{

 

 

/ / в о з в р а щ а е т n u l l

// Можно

р а б о т а т ь

с a S t u d e n t

 

 

 

}

Избавиться от лишней работы можно посредством обобщенных классов, ные коллекции работают как и массивы: вы определяете один и только один тип, кото| рый может храниться в коллекции при ее объявлении.

Обобщенные классы эффективны

Полиморфизм позволяет типу Obj e c t хранить любой другой тип. Однако за удобство приходится платить упаковкой и распаковкой типов-значений при размете] их в необобщенных коллекциях.

Упаковка не так уж снижает эффективность, если ваша коллекция мала. Но если ва перемещаете тысячи или даже миллионы целых чисел типа i n t в необобщенной конлекции, это может занять примерно в 20 раз больше времени (и потребовать дополи тельной памяти) по сравнению с хранением объектов ссылочного типа. Упаковка танк может привести к некоторым трудно находимым ошибкам. Обобщенные коллекции» знакомы с проблемами, связанными с упаковкой и распаковкой.

Использование обобщенных коллекций

Теперь, когда вы знаете, почему обобщенные коллекции предпочтительнее необоб­ щенных, пришло время познакомиться с тем, как они используются. В табл. 15.2 пред-

344

Часть V. За базовыми классам


ставлен частичный список обобщенных классов коллекций (в третьем столбце таблицы указаны их необобщенные эквиваленты).

Помимо указанных классов, имеются й другие, а также несколько соответствующих интерфейсов для большинства из них, таких как I C o l l e c t i o n < T > или I L i s t < T > . За более подробной информацией о них обратитесь к разделу "System.Collections.Generic namespace" справочной системы.

Понятие <Т>

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

тем указания реального типа:

 

|ist<int>

i n t L i s t =

 

new

L i s t < i n t > ( ) ; / /

И н с т а н ц и р о в а н и е д л я i n t

Например,

в

следующем разделе

L i s t < T > будет инстанцирован для типов i n t ,

string и S t u d e n t . Кстати говоря, Т отнюдь не священная корова, и вместо него можно использовать все что угодно — например <dummy> или <mуТуре>. Обычно для паметра типа применяются буквы Т, U, V и т.д.

Использование List<T>

Если A r r a y L i s t — один из наиболее часто используемых необобщенных классов коллекций, то его обобщенный двойник — L i s t < T > . Его применение проиллюстрировано в демонстрационной программе G e n e r i c C o l l e c t i o n s . (Для того чтобы компилировать эту программу, вы должны закомментировать строки, приводящие [ошибкам времени компиляции.) Полный текст программы можно найти на прилагаемом компакт-диске.

// G e n e r i c C o l l e c t i o n s - д е м о н с т р а ц и я обобщенных к о л л е к ц и й using System;

using System . C o l l e c t i o n s ; using System. Collections .Generic; namespace GenericCollections

{

public c l a s s P r o g r a m

15.

Обобщенное программирование

345


p u b l i c

s t a t i c v o i d M a i n ( s t r i n g [ ]

a r g s )

 

 

{

 

 

 

 

 

 

 

 

 

 

/ / О б ъ я в л е н и е A r r a y L i s t д л я с р а в н е н и я

 

 

A r r a y L i s t

a L i s t =

new

A r r a y L i s t ( ) ;

 

 

// L i s t < T > :

о б р а т и т е

внимание

на

у г л о в ы е

с к о б к и и

// п а р а м е т р т и п а Т

 

 

 

 

 

 

L i s t < s t r i n g > s L i s t =

/ /

И н с т а н ц и р о в а н и е

д л я s t r i n g

new

L i s t < s t r i n g > ( ) ;

s L i s t . A d d C ' o n e " ) ;

 

 

//

Ошибка

к о м п и л я ц и и !

s L i s t . A d d ( 3 ) ;

 

 

s L i s t . A d d (

 

 

B o i s " ) ) ; //

Ошибка

к о м п и л я ц и и !

new

S t u d e n t ( " d u

/ / И н с т а н ц и р о в а н и е д л я i n t

 

 

 

 

L i s t < i n t >

i n t L i s t

= new

L i s t < i n t > ( ) ;

 

 

i n t L i s t . A d d ( 3 ) ;

 

/ /

Никакой

у п а к о в к и

 

i n t L i s t . A d d ( 4 ) ;

 

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( " В ы в о д

i n t L i s t : " ) ;

 

 

f o r e a c h ( i n t

i i n

i n t L i s t )

/ / Цикл

f o r e a c h

р а б о т а е т для

 

 

 

 

 

 

/ / в с е х к о л л е к ц и й

{

/ / О б р а т и т е в н и м а н и е : п р и в е д е н и я т и п а н е т

C o n s o l e . W r i t e L i n e ( " i n t i = " + i . T o S t r i n g ( ) ) ;

}

/ / И н с т а н ц и р о в а н и е д л я S t u d e n t

 

 

 

 

L i s t < S t u d e n t >

s t u d e n t L i s t

= new

L i s t < S t u d e n t > ( ) ;

S t u d e n t

s t u d e n t l

=

new

S t u d e n t ( "Vigil 1 1 ) ;

 

S t u d e n t

s t u d e n t 2

=

new

S t u d e n t ( " F i n c h " ) ;

 

s t u d e n t L i s t . A d d ( s t u d e n t l ) ;

 

 

 

 

 

s t u d e n t L i s t . A d d ( s t u d e n t 2 ) ;

 

 

 

 

 

S t u d e n t [ ] s t u d e n t s

= new

S t u d e n t [ ]

 

 

 

{

new S t u d e n t ( " M o x " ) ,

new

S t u d e n t ( " F o x " ) };

 

s t u d e n t L i s t . A d d R a n g e ( s t u d e n t s ) ;

/ / Д о б а в л я е м в е с ь

 

 

 

 

 

 

 

 

// м а с с и в в L i s t

C o n s o l e . W r i t e L i n e ( " С т у д е н т о в в s t u d e n t L i s t = { о } " ,

 

 

 

 

 

s t u d e n t L i s t . C o u n t ) ;

 

 

//

Поиск

при

помощи I n d e x O f ( )

 

 

 

 

C o n s o l e . W r i t e L i n e ( " S t u d e n t 2 в " +

 

 

 

 

 

 

 

 

s t u d e n t L i s t . I n d e x O f ( s t u d e n t 2 ) ) ;

s t r i n g name =

s t u d e n t L i s t [3] .Name;

//

Обращение при

 

 

 

 

 

 

 

 

 

//

помощи

и н д е к с а

i f ( s t u d e n t L i s t . C o n t a i n s ( s t u d e n t l ) )

/ /

Поиск

C o n t a i n s ( )

{

 

 

 

 

 

 

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( s t u d e n t l . N a m e + " е с т ь в с п и с к е " ) ;

}

s t u d e n t L i s t . S o r t ( ) ; / / С ч и т а е м , ч т о S t u d e n t р е а л и з у е т / / и н т е р ф е й с I C o m p a r a b l e

s t u d e n t L i s t . I n s e r t ( 3 , new S t u d e n t ( " R o s s " ) ) ;

s t u d e n t L i s t . R e m o v e A t ( 3 ) ;

/ /

Удаляем э л е м е н т

// name о п р е д е л е н о выше

 

 

C o n s o l e . W r i t e L i n e ( " У д а л я е м { о } " , n a m e ) ;

S t u d e n t [ ] m o r e S t u d e n t s =

 

 

s t u d e n t L i s t . T o A r r a y ( ) ;

//

П р е о б р а з у е м с п и с о к в массив

346

Часть V. За базовыми классами!

Глава


//

Ожидаем

п о д т в е р ж д е н и я п о л ь з о в а т е л я

C o n s o l e . W r i t e L i n e ( " Н а ж м и т е

< E n t e r > для " +

 

 

 

" з а в е р ш е н и я

п р о г р а м м ы . . . " ) . ;

C o n s o l e . R e a d ( ) ;

 

 

 

public

c l a s s S t u d e n t

: I C o m p a r a b l e

 

// См.

полную

версию

программы

на

п р и л а г а е м о м

// к о м п а к т - д и с к е

В приведенном листинге имеется три инстанцирования L i s t < T > : для i n t , s t r i n g в Student. В программе также продемонстрировано следующее:

безопасность типов, позволяющая избежать добавления данных неверного типа; возможность применения для коллекции L i s t < T > цикла f o r e a c h , как и для лю­ бой другой коллекции; добавление объектов, как по одному, так и сразу целым массивом;

сортировка списка (в предположении, что элементы реализуют интерфейс ICom­ p a r a b l e ) ;

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

Это только небольшой пример использования методов L i s t < T > . У других обобщен­ ии коллекций имеются свои наборы методов, однако все они схожи в применении.

Главное улучшение заключается в том, что компилятор предупреждает добав­ ление в коллекцию данных типа, отличного от того, для которого она инстанцирована.

Помимо встроенных обобщенных классов коллекций, С# позволяет написать собственные обобщенные классы — как коллекции, так и другие типы классов. Главное, что вы имеете возможность создать обобщенные версии классов, которые проектированы вами.

Определение обобщенного класса переполнено записями <Т>. Когда вы инстанцируете такой класс, вы указываете тип, который заменит Т так же, как и в случае усмотренных обобщенных коллекций. Посмотрите, насколько схожи приведенные

иже объявления:

 

LinkedList<int> a L i s t

= new L i n k e d L i s t < i n t > () ;

MyClass<int> a C l a s s =

new M y C l a s s < i n t > () ;

toa 15. Обобщенное программирование

347