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

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

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

Добавлен: 11.12.2025

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

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

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

Упаковка типов-значений

Что действительно делает ссылочные типы и типы-значения наподобие i n t , b o o l , char и любой структуры гражданами С# первого сорта — так это технология, назы­ ваемая упаковкой (boxing). Во многих ситуациях компилятор временно конвертирует объекты типов-значений в ссылочные объекты. Упаковка означает перемещение части данных типа-значения в объект ссылочного типа в куче. Вот пример, в котором вы­

полняется упаковка:

 

 

 

 

int i

=

9 9 9 ;

//

П р о с т о й

i n t

( т и п - з н а ч е н и е )

object

о

= i;

//

Помещаем

i в

ссылочную у п а к о в к у

int j

=

( i n t ) о;

//

Получаем

99 9

из у п а к о в к и

Все, что было упаковано, рано или поздно потребует распаковки, которая влечет за собой приведение типа. В демонстрационной программе T y p e U n i f i c a t i o n каждое присваивание o b j e c t требовало упаковки, а обратное преобразование переменной ob­ ject — распаковки.

Обе операции требуют определенного времени. Упаковка до 20 раз продолжительнее обычного присваивания, а распаковка — до 4 раз. Кроме того, упаковка требует допол­ нительной памяти для размещения объекта в куче, так что большое количество упаковок может снизить производительность вашей программы. Упаковка во многих ситуациях выполняется автоматически, включая такие ситуации, как передача аргумента, возврат значения из функции, присваивание, работа с массивами o b j e c t [ ] , вызовы W r i t e ­ Line () и многое другое. По возможности избегайте упаковки — например, вызовами ToString () для значений, передаваемых W r i t e L i n e ( ) , избегая работы с массивами object и используя новые обобщенные коллекции, рассматривающиеся в главе 15, "Обобщенное программирование".

ими классами

[лава 14. Интерфейсы и структуры


Глава 15

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

Коллекционирование: преимущества и проблемы Экономия времени и кода с помощью обобщенных коллекций

Написание собственных обобщенных классов, методов и интерфейсов

# предоставляет массу специализированных альтернатив массивам, о которых речь шла в главе 6, "Объединение данных — классы и массивы". В этой главе I будут рассмотрены списки, стеки, очереди и другие "массивоподобные" классы кол­

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

Однако можно сохранить массу времени и усилий, если воспользоваться обобщенной вер­ сией. Обобщенные классы6 (generics) — новая возможность С#, появившаяся в версии 2.0. Обобщенные классы представляют собой классы, методы и интерфейсы, в которых поля ти­ пов остаются незаполненными. Чтобы понять, о чем идет речь, рассмотрим конкретный при­ мер. Так, класс L i s t < T > определяет обобщенный список, очень похожий на A r r a y L i s t . Когда вы используете этот список для создания {инстанцирования) собственного списка, на­ пример чисел типа i n t , вы заменяете параметр типа Т конкретным типом i n t :

List<int> m y L i s t = new L i s t < i n t > () ; // Список ч и с е л т и п а i n t

Универсальность такого списка состоит в том, что вы можете инстанцировать List<T> для любого единого типа данных — s t r i n g , S t u d e n t , B a n k A c c o u n t — и при этом получить такую же безопасность типов, как у массива, причем без лишних за­ трат. Это — супермассив.

Обобщенные классы в С# могут быть встроенными, такими как L i s t < T > , и пользо­ вательскими, т.е. написанными вами. После чтения этой главы вы научитесь писать соб­ ственные обобщенные классы не хуже встроенных.

°Здесь следует сделать небольшое пояснение. Дело в том, что это новая для С# возможность,

апотому русскоязычная терминология еще не устоялась. В С++, в котором обобщенное программи­ рование было реализовано существенно раньше, обобщенные, или универсальные классы, называют­ ся шаблонами. В С# такие классы именуются generic class, или просто generic. В русскоязычной лите­ ратуре встречаются такие переводы, как обобщенные классы, универсальные классы и даже термин "дженерик". В данной книге будет использоваться термин "обобщенные классы". — Примеч. ред.


Чтобы понять, что такое обобщенные классы и что в них хорошего, давайте начнем рассмотрения обычных классов-коллекций.

Массивы обеспечивают быстрый и эффективный доступ к произвольным ментам. Но зачастую массивы не удовлетворяют вашим требованиям из-за их недостатков.

Программа должна объявить размер массива при его создании. В отличие от Vi ual Basic, С# не позволяет изменять размер массива после его определения! делать, если вы не знаете заранее, массив какого размера вам потребуется?

Вставка или удаление элемента из середины массива весьма неэффективна, 1 должны сдвинуть все элементы, чтобы освободить память.

Для решения этих проблем С# предоставляет ряд необобщенных коллекций в качаз) ве альтернатив массивам. Каждая из коллекций имеет свои сильные и слабые стороны.

Необобщенные коллекции

С# предоставляет ряд хорошо спроектированных альтернатив массивам. В табл. lil описаны несколько наиболее полезных необобщенных коллекций. Вне сомнения, пол характеристикам вы всегда сможете выбрать подходящий класс для решения стояи перед вами задачи (но не спешите — еще немного, и вы познакомитесь с обобщена ми классами).

340

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


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

Коллекции легче применять, чем массивы. Для этого нужно инстанцировать объект коллекции, добавить в него элементы и итеративно работать с ними (для этого лучше всего воспользоваться циклом f o r e a c h ) . Приве­ денная дальше демонстрационная программа иллюстрирует эту последо­ вательность действий.

// N o n g e n e r i c C o l l e c t i o n s

д е м о н с т р а ц и я и с п о л ь з о в а н и я

// классов

к о л л е к ц и й

 

 

 

 

 

using

System;

 

 

 

 

 

 

using

S y s t e m . C o l l e c t i o n s ;

 

 

 

 

 

namespace

 

N o n g e n e r i c C o l l e c t i o n s

 

 

 

(

 

 

 

 

 

 

 

 

 

public

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

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

//

Демонстрация

A r r a y L i s t ,

S t a c k ,

Queue

и

H a s h t a b l e

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 r r a y L i s t a L i s t W i t h S p e c i f i e d S i z e

=

new

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

 

A r r a y L i s t

 

a L i s t

=

new

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

/ /

 

р а з м е р n o

 

 

 

 

 

 

 

 

 

 

 

 

//

 

умолчанию (16)

 

a L i s t . A d d ( " o n e " ) ;

/ / Д о б а в л е н и е в к о н е ц с п и с к а

 

a L i s t . A d d ( " t w o " ) ;

// В с п и с к е - " o n e " , " t w o "

 

a L i s t . A d d ( " t h r e e " ) ; // В с п и с к е - " o n e " , " t w o " , " t h r e e "

 

C o n s o l e . W r i t e L i n e ( " { 0 }

i t e m s

i n t h e A r r a y L i s t : " ,

 

 

 

 

 

 

 

a L i s t . C o u n t ) ;

 

 

 

 

 

 

// Цикл

с

и с п о л ь з о в а н и е м

f o r e a c h

 

 

 

 

 

 

f o r e a c h ( s t r i n g

 

s i n a L i s t )

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//

Выводим

с т р о к у и

ее

и н д е к с

в A r r a y L i s t

 

C o n s o l e . W r i t e L i n e ( s + " в ( { о } ) " ,

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

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

/ / S t a c k

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

/ / И н с т а н ц и р у е м с т е к

 

 

 

 

 

 

 

 

 

S t a c k

s t a c k =

new

S t a c k ( ) ;

 

 

 

 

 

 

 

// Вносим

э л е м е н т ы

в

с т е к

и

снимаем

с

н е г о

один

 

/ / э л е м е н т

 

 

 

 

 

 

 

 

 

 

 

 

s t a c k . P u s h ( " o n e " ) ;

 

 

 

 

 

 

 

 

 

 

s t a c k . P u s h ( " t w o " ) ;

 

/ / " t w o " , " o n e "

 

 

 

 

 

s t a c k . P u s h ( " t h r e e " ) ;

/ / " t h r e e " , " t w o " , " o n e "

 

C o n s o l e . W r i t e L i n e ( " { 0 } э л е м е н т о в в с т е к е :

" ,

 

 

 

 

 

 

 

s t a c k . C o u n t ) ;

 

 

 

 

 

 

f o r e a c h

( s t r i n g s

i n s t a c k )

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( s ) ;

 

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(ma

15.

Обобщенное

программирование

 

 

 

 

341


s t r i n g s v a l = ( s t r i n g ) s t a c k . P o p ( ) ; / / " t w o " , " o n e " C o n s o l e . W r i t e L i n e ( " С н я т э л е м е н т : " ) ;

C o n s o l e . W r i t e L i n e ( s v a l ) ;

C o n s o l e . W r i t e L i n e ( " В е р ш и н а с т е к а : { о } " , s t a c k . P e e k ( ) ) ;

/ /

/ / Queue

/ /

/ / И н с т а н ц и р о в а н и е о ч е р е д и Queue q u e u e = new Q u e u e ( ) ;

// П о с т а н о в к а в о ч е р е д ь н е с к о л ь к и х э л е м е н т о в

q u e u e . E n q u e u e ( " o n e " ) ;

 

 

 

 

 

 

q u e u e . E n q u e u e ( " t w o " ) ;

 

 

 

 

 

 

q u e u e . E n q u e u e ( " t h r e e " ) ;

/ / " o n e " , " t w o " , " t h r e e "

 

C o n s o l e . W r i t e L i n e ( " { 0 }

э л е м е н т о в в о ч е р е д и : " ,

 

 

 

 

 

 

q u e u e . C o u n t ) ;

 

 

 

f o r e a c h

( s t r i n g s

i n q u e u e )

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( s ) ;

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( " В ы в о д и з о ч е р е д и :

{ о } " ,

 

 

 

 

 

 

 

q u e u e . D e q u e u e ( ) ) ;

 

 

 

C o n s o l e . W r i t e L i n e ( " Г о л о в а о ч е р е д и :

{ о } " ,

 

 

 

 

 

 

 

q u e u e . P e e k ( ) ) ;

 

 

 

/ /

 

 

 

 

 

 

 

 

 

 

 

 

/ / H a s h t a b l e

 

 

 

 

 

 

 

 

 

/ /

 

 

 

 

 

 

 

 

 

 

 

 

/ / И н с т а н ц и р о в а н и е H a s h t a b l e ( с л о в а р ь )

 

 

H a s h t a b l e

t a b l e

=

new

H a s h t a b l e ( ) ;

 

 

 

S t u d e n t

s t u d e n t l

=

new

S t u d e n t ( " R a n d y " ) ;

 

 

S t u d e n t

s t u d e n t 2

=

new

S t u d e n t ( " C h u c k " ) ;

 

 

/ /

Д о б а в л я е м

о б ъ е к т

S t u d e n t ,

ключом

я в л я е т с я

е г о

имя

t a b l e . A d d ( s t u d e n t l . N a m e ,

s t u d e n t l ) ;

 

 

 

t a b l e . A d d ( s t u d e n t 2 . N a m e ,

s t u d e n t 2 ) ;

 

 

 

/ /

Порядок

н е и з в е с т е н

 

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( " { 0 }

э л е м е н т о в в

с л о в а р е : " ,

 

 

 

 

 

 

t a b l e . C o u n t ) ;

 

 

 

/ /

Элементы,

в о з в р а щ а е м ы е

и з

с л о в а р я , имеют

тип

 

/ / D i c t i o n a r y E n t r y

 

 

 

 

 

 

 

f o r e a c h ( D i c t i o n a r y E n t r y d e i n t a b l e )

 

 

{

 

 

 

 

 

 

 

 

 

 

 

 

 

// П р и в е д е н и е

с в о й с т в а

D i c t i o n a r y E n t r y . V a l u e к

типу

 

/ / S t u d e n t

 

 

 

 

 

 

 

 

 

 

S t u d e n t s t u =

( S t u d e n t ) d e . V a l u e ;

 

 

 

 

C o n s o l e . W r i t e L i n e ( s t u . N a m e ) ;

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

/ /

Ожидаем

п о д т в е р ж д е н и я

п о л ь з о в а т е л я

 

 

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 ( ) ;

}

p u b l i c c l a s s S t u d e n t

{

342

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