1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 67
Текст из файла (страница 67)
P o p ( ) ; // "two","one"Console.WriteLine("Снятэлемент:");Console.WriteLine(sval);Console.WriteLine("Вершина стека:{о}",stack.Peek());////Queue//// Инстанцирование очередиQ u e u e q u e u e = new Q u e u e ( ) ;// Постановка в очередь нескольких элементовqueue.Enqueue("one");queue.Enqueue("two");queue.Enqueue("three"); // "one","two","three"Console.WriteLine("{0}элементов в очереди:",queue.Count);foreach( s t r i n g s in queue){Console.WriteLine(s);}Console.WriteLine("Вывод из очереди:{о}",queue.Dequeue() ) ;Console.WriteLine("Голова очереди:{о}",queue.Peek());////Hashtable//// Инстанцирование 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 , ключом я в л я е т с я е г оtable.Add(studentl.Name,studentl);t a b l e .
A d d ( s t u d e n t 2.Name,student 2);// Порядок н е и з в е с т е нConsole.WriteLine("{0}элементов в с л о в а р е : " ,table.Count);/ / Э л е м е н т ы , в о з в р а щ а е м ы е и з с л о в а р я , имеют т и п// DictionaryEntryforeach(DictionaryEntry de in table)имя{// Приведение с в о й с т в а D i c t i o n a r y E n t r y . V a l u e// StudentStudent stu =(Student)de.Value;Console.WriteLine(stu.Name);ктипу}}}/ / Ожидаем п о д т в е р ж д е н и я п о л ь з о в а т е л яConsole.WriteLine("Нажмите <Enter> для " +"завершения п р о г р а м м ы . .
. " ) ;Console.Read();publicclassStudent{342Часть V. За базовыми классам!privates t r i n g name;public S t u d e n t ( s t r i n g{t h i s.name = name;name)}publicstringName{get{r e t u r n name;}Подробно останавливаться на том, как работают использованные в демонстрационной программе классы-коллекции, нет необходимости, так как сейчас вы познакомитесь с более интересными обобщенными классами.
Получить информацию о необобщенных классах-коллекциях можно в разделе "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 = n e w 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] ; / / п р е о б р а з у е мГлава15.Обобщенное программированиевstring343Второе следствие в том, что в 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 ra L i s t . A d d ( " a s t r i n g " ) ; //aList.Add(3);//aList.Add(aStudent);//ayListОstringintStudent;-- OK-- OK-- OKОднако если вы поместите в A r r a y L i s t (или другую необобщенную коллекцииобъекты разных несовместимых типов, то как вы потом сможете узнать тип, напримертретьего элемента? Если это S t u d e n t , а вы попытаетесь преобразовать его в stringто получите ошибку времени выполнения программы.Для безопасности следует производить проверку с использованием операторis (рассматривавшегося в главе 12, "Наследование") или альтернативного яратора a s следующим образом:if(aList[i]{StudentisStudent)aStudent//=(Student)aList[i];//илиОбъект-Student?//Да...S t u d e n t a S t u d e n t = a L i s t [i] asi f ( a S t u d e n t != n u l l ){/ / Можно р а б о т а т ь с a S t u d e n tStudent;/ / Получаем S t u d e n t/ / Невозможно, "as"// возвращает n u l l}Избавиться от лишней работы можно посредством обобщенных классов,ные коллекции работают как и массивы: вы определяете один и только один тип, кото|рый может храниться в коллекции при ее объявлении.Обобщенные классы эффективныПолиморфизм позволяет типу O b j 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.Genericnamespace" справочной системы.Понятие <Т>В этой странно выглядящей записи <Т> обозначает место, куда будет помещен некийральный тип.
Чтобы вызвать к жизни этот символический объект, его инстанцируют путем указания реального типа:|ist<int> i n t L i s t =new L i s t < i n t > ( ) ;//ИнстанцированиедляintНапример, в следующем разделе 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 S y s t e m ;using S y s t e m . 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 m15.Обобщенноепрограммированиеобобщенныхколлекций345publicstaticvoidMain(string[]args){// Объявление 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 > : обратите внимание на угловые скобки и// п а р а м е т р типа ТList<string> sList =new L i s t < s t r i n g > ( ) ; / / И н с т а н ц и р о в а н и е д л я s t r i n gsList.AddC'one") ;/ / Ошибка к о м п и л я ц и и !sList.Add(3);sList.Add(n e w S t u d e n t ( " d u B o i s " ) ) ; / / Ошибка к о м п и л я ц и и !// Инстанцирование для i n tL i s t < i n t > i n t L i s t = new L i s t < i n t > ( ) ;intList.Add(3);/ / Никакой упаковкиintList.Add(4);Console.WriteLine("ВыводintList:");f o r e a c h ( i n t i in i n t L i s t )/ / Цикл f o r e a c h р а б о т а е т// всех коллекцийдля{// Обратите внимание: приведения типа нетConsole.WriteLine("int i = " + i.ToString());}// Инстанцирование для S t u d e n tL 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 > ( ) ;11S t u d e n t s t u d e n t l = new S t u d e n t ( "Vigil ) ;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 " ) ;studentList.Add(studentl);studentList.Add(student2);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 " )};studentList.AddRange(students);// Добавляем весь// массив в L i s tConsole.WriteLine("Студентов в studentList = { о } " ,studentList.Count);/ / П о и с к п р и помощи I n d e x O f ( )Console.WriteLine("Student2 в " +studentList.IndexOf(student2));s t r i n g n a m e = s t u d e n t L i s t [3] .
N a m e ; / / О б р а щ е н и е п р и/ / помощи и н д е к с а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 ( ){Console.WriteLine(studentl.Name + " есть в списке");}studentList.Sort();// Считаем, что S t u d e n t реализует// интерфейс IComparables 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 " ) ) ;studentList.RemoveAt(3);/ / Удаляем элемент/ / n a m e о п р е д е л е н о вышеConsole.WriteLine("Удаляем { о } " , name);Student[] moreStudents =s t u d e n t L i s t . T o A r r a y ( ) ; // П р е о б р а з у е м с п и с о к в массив346Часть V.