Кратко съдържание

Том 1

Кратко съдържание. 2

Съдържание. 13

Предговор. 33

Глава 1. Архитектура на платформата .NET и .NET Framework. 69

Глава 2. Въведение в C#. 107

Глава 3. Обектно-ориентирано програмиране в .NET. 143

Глава 4. Управление на изключенията в .NET. 222

Глава 5. Обща система от типове (Common Type System). 249

Глава 6. Делегати и събития. 285

Глава 7. Атрибути. 309

Глава 8. Масиви и колекции. 325

Глава 9. Символни низове (Strings). 363

Глава 10. Регулярни изрази. 421

Глава 11. Вход и изход. 499

Глава 12. Работа с XML. 529

Глава 13. Релационни бази от данни и MS SQL Server. 601

Глава 14. Достъп до данни с ADO.NET. 667

Том 2

Глава 15. Графичен потребителски интерфейс с Windows Forms. 785

Глава 16. Изграждане на уеб приложения с ASP.NET. 786

Глава 17. Многонишково програмиране и синхронизация. 787

Глава 18. Мрежово и Интернет програмиране. 788

Глава 19. Отражение на типовете (Reflection). 789

Глава 20. Сериализация на данни. 790

Глава 21. Уеб услуги с ASP.NET. 791

Глава 22. Отдалечено извикване на методи (Remoting). 792

Глава 23. Взаимодействие с неуправляван код. 793

Глава 24. Управление на паметта и ресурсите. 794

Глава 25. Асемблита и разпространение. 795

Глава 26. Сигурност в .NET Framework. 796

Глава 27. Mono - свободна имплементация на .NET. 797

Глава 28. Помощни инструменти за .NET разработчици. 798

Глава 29. Практически проект. 799

Заключение. 800

 


Програмиране за .NET Framework

 

Светлин Наков и колектив

 

 


Александър Русев

Александър Хаджикръстев

Антон Андреев

Бранимир Ангелов

Васил Бакалов

Виктор Живков

Галин Илиев

Георги Пенчев

Деян Варчев

Димитър Бонев

Димитър Канев

Ивайло Димов

Ивайло Христов

Иван Митев

Лазар Кирчев

Манол Донев

Мартин Кулов

Михаил Стойнов

Моника Алексиева

Николай Недялков

Панайот Добриков

Преслав Наков

 

Радослав Иванов

Светлин Наков

Стефан Добрев

Стефан Захариев

Стефан Кирязов

Стоян Дамов

Тодор Колев

Христо Дешев

Христо Радков

Цветелин Андреев

Явор Ташев


 

 

 

Българска асоциация на разработчиците на софтуер

София, 2004-2005


Програмиране за .NET Framework

 

© Българска асоциация на разработчиците на софтуер (БАРС), 2005 г.

© Издателство "Фабер", 2005 г.

 

 

Настоящата книга се разпространява свободно при следните условия:

Читателите имат право:

-     да използват книгата и учебните материали към нея или части от тях за всякакви цели, включително да ги да променят според своите нужди и да ги използват при извършване на комерсиална дейност;

-     да използват сорс кода от примерите и демонстрациите, включени към книгата и учебните материали или техни модификации, за всякакви нужди, включително и в комерсиални софтуерни продукти;

-     да разпространяват безплатно непроменени копия на книгата и учеб­ните материали в електронен или хартиен вид;

-     да разпространяват безплатно оригинални или променени части от учебните материали, но само при изричното споменаване на източника и авторите на съответния текст, програмен код или друг материал.

Читателите нямат право:

-     да разпространяват срещу заплащане книгата, учебните матери­али или части от тях (включително модифицирани версии), като изключе­ние прави само програмният код;

-     да премахват настоящия лиценз от книгата или учебните материали.

 

Всички запазени марки, използвани в тази книга, са собственост на техните притежатели.

 

 

Официален сайт:

www.devbg.org/dotnetbook/

 

ISBN 954-775-505-6


Национална академия по разработка на софтуер

Лекторите

» Светлин Наков е автор на десетки технически публи­ка­ции и ня­колко книги, свър­­зани с раз­работката на соф­ту­ер, заради което е тър­сен лектор и кон­султант.

Той е разработчик с дъл­гого­дишен опит, работил по раз­нообразни проекти, реали­зи­рани с раз­лични техноло­гии (.NET, Java, Oracle, PKI и др.) и преподавател по съвре­мен­ни софтуерни технологии в СУ "Св. Климент Охридски".

През 2004 г. е носител на награ­дата "Джон Атанасов" на прези­дента на България Ге­орги Пър­ва­нов.

Светлин Наков ръководи обу­чението по Java технологии в Академията.

 

» Мартин Кулов е софтуерен инженер и консул­тант с дългогодишен опит в изграждането на решения с платформите на Microsoft.

Мартин е опитен инструктор и сертифициран от Майкрософт разработчик по програмите MCSD, MCSD.NET, MCPD и MVP и меж­дународен лектор в световна­та организа­ция на .NET потре­бителски­те групи INETA.

Мартин Кулов ръководи обу­чението по .NET технологии в Академията.

Академията

» Национална академия по раз­ра­ботка на софтуер (НАРС) е център за професионално обу­чение на соф­ту­ерни специалисти.

 

» НАРС провежда БЕЗПЛАТНО кур­сове по разработка на софтуер и съв­ременни софтуерни тех­нологии в Со­фия и други градове.

 

» Предлагани специалности:

§  Въведение в програмирането (с езиците C# и Java)

§  Core .NET Developer

§  Core Java Developer

 

» Качествено обу­чение с много практически про­екти и индивиду­ално внимание за всеки.

 

» Гарантирана работа! Трудов до­говор при постъпване в Академията.

 

» БЕЗПЛАТНО!

Учите безплатно във въведителните курсове и по стипендии от работода­телите в следващите нива.

http://academy.devbg.org




 

 

 


 

 

www.devbg.org

 

 

Българска асоциация на разработчиците на софтуер (БАРС) е нестопанска организация, която подпомага про­фе­сионалното развитие на българските софтуерни специ­а­листи чрез образо­вателни и други инициативи.

БАРС работи за насърчаване обмяната на опит между раз­работ­чиците и за усъвършенстване на техните знания и умения в областта на проектирането и разработката на софтуер.

Асоциацията организира специализирани конференции, семи­нари и курсове за обучение по разработка на софту­ер и софту­ерни технологии.

БАРС организира създаването на Национална академия по раз­работка на софтуер – учебен център за професионал­на подго­товка на софтуерни специалисти.

 


Отзив от Теодор Милев

 

Свидетели сме как платформата Microsoft .NET се налага все повече в света на софтуерните технологии. Тази тенденция се наблюдава и в България, където прогресивно нараства броят на проектите, реализирани на базата на .NET. С увеличаване на .NET разработчиците расте и нуждата от качествена техническа литература и учебни материали, които да бъдат използвани при обучението на .NET специалисти.

"Програмиране за .NET Framework" е първата чисто българска книга за Microsoft .NET технологиите. Тя представя на читателя в последователен, структуриран, достъпен и разбираем вид основните концепции за разра­ботка на приложения с .NET Framework и езика C#. Книгата обхваща в детайли всички основни .NET технологии като набляга върху най-важните от тях – ADO.NET, ASP.NET, Windows Forms и XML уеб услуги.

По качество на изложения материал книгата се отличава с високо профе­сионално ниво и превъзхожда повечето преводни издания по темата. Тя е отлично структурирана, а стилът на изложени­ето е лесен за възприемане. Инфор­мацията е поднесена с много примери, а това е най-важното за един софтуерен разработчик.

Книгата е написана от широк екип доказани специалисти, работещи в партньорските фирми на Майкрософт – хора с опит в разработката на .NET приложения. Основният автор и ръководител на проекта, Светлин Наков, е изтъкнат .NET специалист, лектор в множество семинари и кон­ференции, търсен консул­тант и преподавател. Негови са заслугите за курсовете по програ­миране за платформа .NET във Факултета по матема­тика и информатика на Софийски университет. Негови са и основните заслуги за целия проект по изготвяне на изчерпателно учебно съдържа­ние и книга по програми­ране за .NET Framework.

Светлин Наков е носител на най-голямото отличие в областта на информа­ционните технологии – наградата "Джон Атанасов" на Президента Георги Първанов за принос към развитието на информационните техно­логии информационното общество. Той е автор на десетки статии и книги за програмиране, а настоящото издание е поредната му добра изява.

Настоящата книга е отлично учебно пособие както за начинаещи, така и за напреднали читатели, които имат желание и амбиции да станат профе­сионални .NET разработчици.

 

Теодор Милев,

Управляващ директор на "Майкрософт България"


Отзив от Божидар Сендов

 

Книгата е оригинално българско творение, с нищо неотстъпващо по качество и обем на световните бестселъри с компютърна тематика. Мате­риалът е поднесен достъпно и е богато илюстриран с примери, което я прави не само отлично въведение в платформата .NET за начинаещия, но и отличен справочник за професионалиста-програмист на C#. Читателят може да се запознае в детайли не само с общите принципи, но и с редица тънкости на програмирането за .NET. Широко застъпени са редица "уни­версални" теми като обектно-ориентирано програмиране, регулярни изра­зи, XML, релационни бази данни, програмиране в Интернет, многозадач­ност, сигурност и др.

Книгата се отличава със стегнат и ясен стил на изложението, като е постигнато завидно педагогическо майсторство. Това не бива да ни изне­надва – авторите са водещи специалисти с богат опит не само като профе­сионални софтуерни разработчици, но и като преподаватели във Факул­тета по математика и информатика (ФМИ) на СУ "Св. Климент Охридски". Самата книга в значителна степен се основава на работни лекции, изпол­звани и проверени в поредица от курсове по програмиране за .NET Framework във ФМИ. Сайтът на книгата съдържа над 2000 безплатни слайда, следващи стриктно съдържанието й, а книгата е напълно безплат­на в електронния си вариант, което максимално улеснява използването й в съответен курс по програмиране.

Не на последно място, заслужава да се отбележи систематичният опит за превод на всички термини на български език, съобразен с вече наложи­лата се българска терминология, но и с оригинални идеи при новите понятия.

Работата, която авторите са свършили, е наистина чудесна, а книгата е задължителна част от библиотеката на всеки с интерес към езика C# и изобщо към водещата платформа на Майкрософт .NET.

 

 

 

доц. д-р Божидар Сендов

Факултет по математика и Информатика,

Софийски Университет "Св. Климент Охридски"


Отзив от Стоян Йорданов

 

"Програмиране за .NET Framework" е уникално ръководство за платформа­та .NET. Въпреки, че не е учебник по програмиране, книгата е изключи­телно подходяща както за начинаещия програмист, сблъскващ се за пръв път с .NET, така и за опитния разработчик на .NET приложения, целящ да систематизира и попълни знанията си. Всяка тема в "Програмиране за .NET Framework" започва с основите на разглежданите в нея технологии, но към края на темата читателят е вече запознат с детайлите и тънкос­тите, необходими за успешното им прилагане в практиката.

Обхващайки най-важните аспекти на .NET Framework, книгата започва от основите на езика C# и .NET платформата и постепенно достига до сложни концепции като уеб услуги, сигурност, сериализация, работа с отдалечени обекти, манипулиране на бази данни чрез ADO.NET, потреби­телски интерфейс с Windows Forms, ASP.NET уеб приложения и т.н. Информацията е поднесена изключително достъпно и подкрепена с много­бройни примери и илюстрации. Всяка тема включва и упражнения за самостоятелна работа – неотменим елемент за затвърдяване на придоби­тите от нея знания.

Авторският колектив включва утвърдени специалисти от софтуерните среди. Въпреки, че авторите са над 30, "Програмиране за .NET Framework" не е просто сборник от статии; напротив – всеки от тях е допринесъл с опита и труда си, за да може книгата да бъде това, което е – добре структурирано и изчерпателно ръководство.

Учебник за студента или справочник за специалиста – "Програмиране за .NET Framework" е задължителна за библиотеката на всеки който има досег с .NET.

 

 

 

 

 

Стоян Йорданов,

Software Design Engineer,

Microsoft Corpartion (Redmond)

 

* Мнението е лично на автора му и не обвързва Microsoft Corporation по никакъв начин


Национална академия по разработка на софтуер

Лекторите

» Светлин Наков е автор на десетки технически публи­ка­ции и ня­колко книги, свър­­зани с раз­работката на соф­ту­ер, заради което е тър­сен лектор и кон­султант.

Той е разработчик с дъл­гого­дишен опит, работил по раз­нообразни проекти, реали­зи­рани с раз­лични техноло­гии (.NET, Java, Oracle, PKI и др.) и преподавател по съвре­мен­ни софтуерни технологии в СУ "Св. Климент Охридски".

През 2004 г. е носител на награ­дата "Джон Атанасов" на прези­дента на България Ге­орги Пър­ва­нов.

Светлин Наков ръководи обу­чението по Java технологии в Академията.

 

» Мартин Кулов е софтуерен инженер и консул­тант с дългогодишен опит в изграждането на решения с платформите на Microsoft.

Мартин е опитен инструктор и сертифициран от Майкрософт разработчик по програмите MCSD, MCSD.NET, MCPD и MVP и меж­дународен лектор в световна­та организа­ция на .NET потре­бителски­те групи INETA.

Мартин Кулов ръководи обу­чението по .NET технологии в Академията.

Академията

» Национална академия по раз­ра­ботка на софтуер (НАРС) е център за професионално обу­чение на соф­ту­ерни специалисти.

 

» НАРС провежда БЕЗПЛАТНО кур­сове по разработка на софтуер и съв­ременни софтуерни тех­нологии в Со­фия и други градове.

 

» Предлагани специалности:

§  Въведение в програмирането (с езиците C# и Java)

§  Core .NET Developer

§  Core Java Developer

 

» Качествено обу­чение с много практически про­екти и индивиду­ално внимание за всеки.

 

» Гарантирана работа! Трудов до­говор при постъпване в Академията.

 

» БЕЗПЛАТНО!

Учите безплатно във въведителните курсове и по стипендии от работода­телите в следващите нива.

http://academy.devbg.org


Съдържание

Том 1

Кратко съдържание. 2

Съдържание. 13

Предговор. 33

За кого е предназначена тази книга? 33

Необходими начални познания. 34

Какво представлява .NET Framework? 34

Какво обхваща тази книга? 34

Фокусът е върху .NET Framework 1.1. 35

Как е представена информацията? 35

Защо C#? 36

Поглед към съдържанието на книгата. 37

Глава 1. Архитектура на .NET Framework. 37

Глава 2. Въведение в езика C#.. 38

Глава 3. Обектно-ориентирано програмиране в .NET. 38

Глава 4. Обработка на изключения в .NET. 38

Глава 5. Обща система от типове. 39

Глава 6. Делегати и събития. 39

Глава 7. Атрибути. 39

Глава 8. Масиви и колекции. 39

Глава 9. Символни низове. 40

Глава 10. Регулярни изрази. 40

Глава 11. Вход/изход. 40

Глава 12. Работа с XML. 41

Глава 13. Релационни бази от данни и MS SQL Server 41

Глава 14. ADO.NET и работа с данни. 41

Глава 15. Графичен потребителски интерфейс с Windows Forms. 42

Глава 16. Изграждане на уеб приложения с ASP.NET. 42

Глава 17. Многонишково програмиране и синхронизация. 43

Глава 18. Мрежово и Интернет програмиране. 43

Глава 19. Отражение на типовете (Reflection) 43

Глава 20. Сериализация на данни. 44

Глава 21. Уеб услуги с ASP.NET. 44

Глава 22. Отдалечено извикване на методи (Remoting) 44

Глава 23. Взаимодействие с неуправляван код. 45

Глава 24. Управление на паметта и ресурсите. 45

Глава 25. Асемблита и разпространение (deployment) 45

Глава 26. Сигурност в .NET Framework. 45

Глава 27. Mono - свободна имплементация на .NET. 46

Глава 28. Помощни инструменти за .NET разработчици. 46

Глава 29. Практически проект. 46

За използваната терминология. 47

Конвенция за кода. 47

Константите пишем с главни букви. 47

Член-променливите пишем с префикс "m". 48

Параметрите на методите пишем с префикс "a". 48

Именуване на идентификатори. 48

Именуване на контроли. 49

Конвенции за базата данни. 49

Как възникна тази книга? 49

Курсът по програмиране за платформа .NET в СУ (2002/2003 г.) 50

Проектът на Microsoft Research и БАРС. 50

Курсът по програмиране за .NET Framework в СУ (2004/2005 г.) 51

Курсът по програмиране за .NET Framework в СУ (2005/2006 г.) 51

Проектът за настоящата книга. 51

Авторският колектив. 53

Александър Русев. 53

Александър Хаджикръстев. 53

Антон Андреев. 53

Бранимир Ангелов. 54

Васил Бакалов. 54

Виктор Живков. 54

Деян Варчев. 55

Димитър Бонев. 55

Димитър Канев. 55

Галин Илиев. 55

Георги Пенчев. 56

Иван Митев. 56

Ивайло Димов. 56

Ивайло Христов. 56

Лазар Кирчев. 57

Манол Донев. 57

Мартин Кулов. 57

Михаил Стойнов. 58

Моника Алексиева. 58

Николай Недялков. 58

Панайот Добриков. 59

Преслав Наков. 59

Радослав Иванов. 59

Светлин Наков. 60

Стефан Добрев. 60

Стефан Кирязов. 60

Стефан Захариев. 61

Стоян Дамов. 61

Тодор Колев. 61

Христо Дешев. 61

Христо Радков. 62

Цветелин Андреев. 62

Явор Ташев. 62

Благодарности. 63

Светлин Наков. 63

Авторският колектив. 63

Българска асоциация на разработчиците на софтуер. 63

Microsoft Research. 63

SciForge.org. 64

Софийски университет "Св. Климент Охридски". 64

telerik. 64

Други. 64

Сайтът на книгата. 65

Лиценз 65

Общи дефиниции. 65

Права и ограничения на потребителите. 66

Права и ограничения на авторите. 66

Права и ограничения на БАРС. 67

Права и ограничения на Microsoft Research. 67

Глава 1. Архитектура на платформата .NET и .NET Framework. 69

Необходими знания. 69

Съдържание. 69

В тази тема ... 69

Какво представлява платформата .NET? 71

Визията на Microsoft 71

Архитектура на .NET платформата. 72

.NET Enterprise Servers. 72

.NET Framework и Visual Studio .NET 2003. 74

.NET Building Block Services. 74

.NET Smart Clients. 74

Какво е .NET Framework? 75

Компоненти на .NET Framework. 76

Архитектура на .NET Framework. 76

Операционна система. 77

Common Language Runtime. 77

Base Class Library. 77

ADO.NET и XML. 77

ASP.NET и Windows Forms. 77

Езици за програмиране. 78

Common Language Runtime. 78

Задачи и отговорности на CLR. 78

Управляван код. 80

Управление на паметта. 82

Intermediate Language (IL) 82

Компилация и изпълнение. 83

Архитектура на CLR. 85

Как CLR изпълнява IL кода?. 86

Асемблита. 88

Проблемът "DLL Hell". 88

Метаданни. 89

IL код. 89

Ресурси. 89

Разгръщане на асемблита. 90

.NET приложения. 90

Преносими изпълними файлове. 91

Application domains 92

Интеграция на езиците за програмиране. 92

Common Language Specification (CLS) 93

Common Type System (CTS) 93

Common Language Infrastructure (CLI) 94

.NET езиците. 95

Framework Class Library. 97

Пакетите от FCL. 98

Visual Studio .NET. 99

Писане на код. 99

Създаване на потребителски интерфейс. 100

Компилиране. 101

Изпълняване и тестване. 102

Проследяване на грешки. 102

Създаване на инсталационен пакет. 103

Получаване на помощ.. 104

VS.NET е силно разширяема среда. 104

Упражнения. 104

Използвана литература. 105

Глава 2. Въведение в C#. 107

Необходими знания. 107

Съдържание. 107

В тази тема... 107

Какво е C#. 108

Принципи при дизайна на езика C#. 108

Компонентно-ориентиран. 108

Всички данни са обекти. 108

Сигурност и надеждност на кода. 109

Всичкият код е на едно място. 111

Програмите на C#. 112

Нашата първа програма на C#.. 112

Как работи програмата?. 112

Създаване на проект, компилиране и стартиране от Visual Studio.NET. 114

Запазени думи в C#. 116

Типове данни в C#. 116

Стойностни типове (value types) 117

Референтни типове (reference types) 117

Примитивни типове. 117

Типове дефинирани от потребителя. 118

Преобразуване на типовете. 118

Изброени типове (enumerations) 119

Идентификатори. 120

Декларации. 121

Константи. 121

Оператори. 122

Изрази (expressions) 122

Програмни конструкции (statements) 122

Елементарни програмни конструкции. 122

Съставни конструкции. 123

Програмни конструкции за управление. 123

Специални конструкции. 126

Коментари в програмата. 127

Вход и изход от конзолата. 127

Вход от конзолата. 127

Изход към конзолата. 128

Дебъгерът на Visual Studio .NET. 129

Инструментът ILDASM. 131

XML документация в C#. 132

Тагове в XML документацията. 133

Извличане на XML документация от C# сорс код. 134

Генериране на HTML документация от VS.NET. 136

Директиви на предпроцесора. 136

Директиви за форматиране на сорс кода. 137

Директиви за условна компилация. 137

Директиви за контрол над компилатора. 138

Документацията на .NET Framework. 138

MSDN Library. 139

.NET Framework и MSDN Library. 139

Упражнения. 140

Използвана литература. 141

Глава 3. Обектно-ориентирано програмиране в .NET. 143

Необходими знания. 143

Съдържание. 143

В тази тема ... 143

Предимства и особености на ООП. 145

Моделиране на обекти от реалния свят. 145

Преизползване на програмния код. 145

Основни принципи на ООП. 145

Капсулация на данните. 145

Наследяване. 146

Полиморфизъм. 146

Основни понятия в ООП. 147

Клас. 147

Обект. 147

Инстанциране. 147

Свойство. 147

Метод. 147

Интерфейс. 147

Наследяване на класове. 148

Абстракция на данните. 148

Абстракция на действията. 148

ООП и .NET Framework. 148

Типове данни. 149

Реализация на понятието клас. 149

Множествено наследяване. 149

Класове. 150

Членове на тип. 151

Видимост на членовете. 151

Член-променливи. 152

Константни полета. 153

Полета само за четене. 154

Методи. 154

Статични членове. 157

Конструктори. 158

Статичен конструктор. 163

Свойства. 166

Индексатори. 171

Структури. 177

Структури – пример. 177

Предаване на параметрите. 178

Параметри за връщане на стойност (out) 178

Предаване по референция (ref) 180

Предаване по стойност (in) 181

Променлив брой параметри. 183

Предаване на променлив брой параметри от различен тип. 183

Предефиниране на оператори. 184

Приоритет и асоциативност. 184

Операторите в C#.. 185

Предефинируеми оператори. 185

Предефиниране на оператори – пример. 185

Наследяване. 191

Класове, които не могат да се наследяват (sealed) 192

Наследяване при структурите. 192

Конвертиране на обекти. 193

Интерфейси. 195

Членове на интерфейс. 195

Реализиране на интерфейс. 196

Обекти от тип интерфейс. 199

Явна имплементация на интерфейс. 201

Абстрактни класове. 203

Абстрактни членове. 203

Наследяване на абстрактни класове. 204

Виртуални членове. 207

Предефиниране и скриване. 207

Клас диаграми. 210

Изобразяване на типовете и връзките между тях. 210

Пространства от имена  (namespaces) 213

Дефиниране. 213

Достъп до типовете. 213

Подпространства. 214

Как да организираме пространствата?. 216

Принципи при обектно-ориентирания дизайн. 217

Функционална независимост (loose coupling) 217

Силна логическа свързаност (strong cohesion) 218

Упражнения. 218

Използвана литература. 220

Глава 4. Управление на изключенията в .NET. 222

Необходими знания. 223

Съдържание. 223

В тази тема ... 223

Изключенията в ООП. 224

Изключенията в .NET Framework. 224

Прихващане на изключения. 225

Програмна конструкция try-catch. 225

Как CLR търси обработчик за изключенията?. 226

Прихващане на изключения – пример. 227

Прихващане на изключения на нива – пример. 228

Свойства на изключенията. 229

Йерархия на изключенията. 231

Подредбата на catch блоковете. 232

Изключения и неуправляван код. 233

Предизвикване (хвърляне) на изключения. 234

Хвърляне и прихващане на изключения – пример. 234

Хвърляне на прихванато изключение – пример. 235

Собствени изключения. 236

Дефиниране на собствени изключения. 237

Собствени изключения – пример. 237

Конструкцията try–finally. 241

Къде е проблемът?. 241

Решението. 241

Конструкцията try-catch-finally. 242

try-finally за освобождаване на ресурси. 244

Препоръчвани практики. 245

Упражнения. 246

Използвана литература. 247

Глава 5. Обща система от типове (Common Type System). 249

Необходими знания. 249

Съдържание. 249

В тази тема ... 249

Какво е CTS? 250

CTS и езиците за програмиране в .NET. 250

CTS e обектно-ориентирана. 250

CTS описва .NET типовете. 250

Стойностни и референтни типове. 250

Къде са ми указателите?. 251

Йерархията на типовете. 251

Типът System.Object 252

Стойностни типове (value types) 252

Референтни типове (reference types) 253

Стойностни срещу референтни типове. 254

Стойностни и референтни типове – пример. 255

Защита от неинициализирани променливи. 258

Автоматична инициализация на променливите. 258

Типът System.Object 259

Защо стойностните типове наследяват референтния тип System.Object?. 259

Потребителските типове скрито наследяват System.Object 260

Методите на System.Object 260

Предефиниране на сравнението на типове. 261

Оператори за работа с типове в C#. 264

Оператор is. 264

Оператор as. 264

Оператор typeof 264

Оператори is и as – пример. 265

Клониране на обекти. 266

Плитко клониране. 266

Дълбоко клониране. 267

Плитки срещу дълбоки копия. 267

Интерфейсът ICloneable. 267

Клониране на обекти в .NET Framework. 267

Имплементиране на ICloneable – пример. 268

Опаковане (boxing) и разопаковане (unboxing) на стойностни типове. 270

Опаковане (boxing) на стойностни типове. 271

Разопаковане (unboxing) на опаковани типове. 271

Особености при опаковането и разопаковането. 272

Как работят опаковането и разопаковането?. 272

Пример за опаковане и разопаковане. 273

Аномалии при опаковане и разопаковане. 273

Интерфейсът IComparable. 276

Системни имплементации на IComparable. 276

Имплементиране на IComparable – пример. 276

Интерфейсите IEnumerable и IEnumerator 278

Интерфейсът IEnumerable. 278

Интерфейсът IEnumerator 279

Имплементиране на IEnumerable и IEnumerator 279

Упражнения. 282

Използвана литература. 283

Глава 6. Делегати и събития. 285

Необходими знания. 285

Съдържание. 285

В тази тема ... 285

Какво представляват делегатите? 286

Инстанциране на делегат. 286

Делегатите и указателите към функции. 286

Callback методи и делегати. 286

Статични или екземплярни методи. 286

Пример за делегат. 287

Видове делегати. 287

Единични (singlecast) делегати. 288

Множествени (multicast) делегати. 288

Инструментът .NET Reflector 293

Използване на .NET Reflector 293

Събития (Events) 294

Шаблонът "Наблюдател". 294

Изпращачи и получатели. 294

Събитията в .NET Framework. 295

Деклариране на събития. 295

Операции върху събития. 295

Разлика между събитие и делегат. 295

Конвенция за събитията. 296

Събития – пример. 297

Делегатът System.EventHandler 301

Пример за използване на System.EventHandler 302

Събития и интерфейси. 303

Имплементиране на събития в интерфейс. 303

Събития и интерфейси – пример. 303

Интерфейси, събития, делегати. 305

Упражнения. 307

Използвана литература. 308

Глава 7. Атрибути. 309

Необходими знания. 309

Съдържание. 309

В тази тема ... 309

Какво представляват атрибутите в .NET? 310

Прилагане на атрибути. 310

Атрибутите са обекти. 312

Параметри на атрибутите. 312

Задаване на цел към атрибут. 313

Къде се използват атрибутите? 314

Декларативно управление на сигурността. 315

Използване на автоматизирана сериализация на обекти. 315

Компонентен модел на .NET. 316

Създаване на уеб услуги в ASP.NET. 316

Взаимодействие с неуправляван (Win32) код. 317

Синхронизация при многонишкови приложения. 317

Дефиниране на собствени атрибути. 317

Собствени атрибути – пример. 317

Дефиниране на собствен атрибут – пример. 318

Извличане на атрибути от асембли. 320

Мета-атрибутът AttributeUsage. 320

Как се съхраняват атрибутите? 321

Какво се случва по време на компилация?. 322

Какво се случва при извличане на атрибут?. 322

Упражнения. 322

Използвана литература. 323

Глава 8. Масиви и колекции. 325

Необходими знания. 325

Съдържание. 325

В тази тема ... 325

Какво e масив? 326

Деклариране на масиви. 326

Заделяне на масиви. 326

Масивите в .NET Framework. 326

Елементи на масивите. 327

Видове масиви. 327

Масиви – пример. 328

Прости числа – пример. 328

Масиви от референтни типове – пример. 330

Многомерни масиви. 331

Инициализиране и достъп до елементите. 331

Разположение в паметта. 332

Многомерни масиви – пример. 332

Масиви от масиви. 334

Инициализиране и достъп до елементите. 335

Разположение в паметта. 335

Триъгълник на Паскал – пример. 336

Типът System.Array. 337

Свойства. 337

Методи. 338

Имплементирани интерфейси. 339

Създаване на ненулево-базиран масив – пример. 339

Сортиране на масиви. 341

Сортиране на масиви – пример. 342

Сортиране с IComparer – пример. 342

Двоично търсене. 344

Двоично търсене – пример. 344

Съвети за работа с масиви. 345

Какво е колекция? 346

Колекциите в .NET Framework. 346

Списъчни и речникови колекции. 346

Колекциите са слабо типизирани. 346

Интерфейсите за колекции. 347

Списъчни колекции. 348

Интерфейсът IList 348

Класът ArrayList 348

Други списъчни колекции. 350

Речникови колекции. 352

Интерфейсът IDictionary. 352

Класът Hashtable. 352

Производителност на Hashtable. 354

Собствени хеш-функции. 356

Класът SortedList 358

Силно типизирани колекции. 359

Специални колекции. 359

Упражнения. 360

Използвана литература. 361

Глава 9. Символни низове (Strings). 363

Необходими знания. 363

Съдържание. 363

В тази тема ... 363

Стандартът Unicode. 364

В началото бе ASCII 364

Unicode. 365

Символите в Unicode. 365

Кодови двойки. 366

Графични знаци (графеми) 367

Типът System.Char 367

Методи за класификация на символите. 367

Методи за смяна на регистъра. 368

Символни низове в .NET Framework. 368

Символните низове и паметта. 368

Класът System.String. 370

Правила за сравнение на символни низове. 370

Методи и свойства на System.String. 371

Escaping последователности. 379

Ефективно конструиране на низове чрез класа StringBuilder 381

Проблемът с долепването на низове. 381

Решението на проблема – класът StringBuilder 382

Членове на StringBuilder 383

Използване на StringBuilder – пример. 384

Задаване на първоначален размер за StringBuilder 385

Сравнение на скоростта на String и StringBuilder – пример. 386

Класът StringInfo. 387

Използване на StringInfo – пример. 388

Интерниране на низове. 389

Форматиращи низове. 390

Използване на форматиращи символи. 390

Форматиране на числа. 390

Отместване при форматирането. 393

Форматиране на дати и часове. 393

Потребителско форматиране. 395

Интернационализация. 397

Културите в .NET Framework. 397

Класът CultureInfo. 397

Свойства на класа CultureInfo. 397

Класът CultureInfo – пример. 398

Списък на културите – пример. 399

Извличане на списък от всички култури в .NET Framework – пример. 399

Парсване на типове. 401

Парсване на числови типове. 401

Парсване на дати. 404

Кодиращи схеми. 405

Кодиращи схеми UTF. 405

UTF-8. 406

UTF-16. 406

UTF-32. 407

Подредба на байтовете при UTF-16 и UTF-32. 407

Други кодиращи схеми. 408

Кодиращи схеми – пример. 408

Конвертиране със System.Text.Encoding. 409

Кодиране Base64. 411

Работа с Unicode във Visual Studio.NET. 412

Упражнения. 416

Използвана литература. 419

Глава 10. Регулярни изрази. 421

Необходими знания. 421

Съдържание. 421

В тази тема ... 421

Регулярни изрази. 422

Какво е регулярен израз?. 422

За какво се използват регулярните изрази?. 422

Регулярни изрази и крайни автомати. 423

История на регулярните изрази. 423

Няколко прости примера. 424

Лесен пример за начало. 424

Търсене на телефонни номера. 425

Пример за регулярен израз в .NET. 425

Езикът на регулярните изрази. 426

Литерали. 426

Метасимволи. 426

Escaping при регулярните изрази. 427

Най-важното за работата с регулярни изрази. 429

Шаблонът не е за съвпадение с целия низ. 429

Съвпаденията се откриват в реда на срещане. 429

Търсенето приключва, когато се открие съвпадение. 430

Търсенето продължава от последното съвпадение. 430

Регулярният израз търси за всички възможности подред. 430

Основни метасимволи. 430

Класове от символи. 431

Метасимволи за количество. 434

"Мързеливи" метасимволи за количество. 436

Метасимволи за местоположение. 438

Метасимволът за избор | 441

По-обстоен пример с разгледаните метасимволи. 442

Регулярните изрази в .NET Framework. 444

Пространството System.Text.RegularExpressions. 444

Представяне на шаблони. 445

Търсене с регулярни изрази. 446

Няколко основни правила при търсенето. 446

Класът Match. 447

Последователно еднократно търсене с Match(…) и NextMatch() 448

Тагове за хипервръзки в HTML код – пример. 448

Още нещо за позицията на следващото търсене. 450

Търсене за съвпадения наведнъж с Matches(…) и MatchCollection. 451

Групи в регулярните изрази. 452

Предимства на групите. 452

Неименувани (анонимни) групи. 453

Именувани групи. 454

Номериране на групите. 454

Търсене с групи в .NET. 455

Класовете Group и GroupCollection. 455

Как извличаме информацията от групите?. 455

Парсване на лог – пример. 457

Извличане на хипервръзки в HTML документ – пример. 458

Работа с обратни препратки. 459

Обратни препратки към именувани групи. 460

Извличане на HTML тагове от документ пример. 461

Работа с Captures 463

Валидация с регулярни изрази. 465

Видове валидация. 465

Полезни съвета за валидация с регулярни изрази. 465

Валидация с метода IsMatch(…) 466

Валидни e-mail адреси – пример. 466

Валидни положителни цели числа – пример. 467

Заместване с регулярни изрази. 468

Заместване със заместващ шаблон. 468

Специални символи в заместващия шаблон. 469

Заместване с MatchEvaluator 471

Разделяне на низ по регулярен израз 471

Разделяне с групи в шаблона. 472

Методите Escape(…) и Unescape(…) 473

Методът Unescape(…) 474

Настройки и опции при работа с регулярните изрази. 474

Multiline. 475

Singleline. 475

IgnoreCase. 475

ExplicitCapture. 476

RightToLeft 476

Compiled. 477

Допълнителни възможности на синтаксиса на регулярните изрази. 477

Символът \G – последователни съвпадения. 477

Групи, които не запазват съвпадение. 478

Метасимволи за преглед напред и назад. 479

Условен избор. 480

Коментари в регулярните изрази. 482

Модификатори на регулярните изрази. 482

Особености и метасимволи, свързани с Unicode. 483

Метасимволите за Unicode категории. 483

Възможни проблеми с Unicode. 484

Предварително компилиране и запазване на регулярни изрази. 485

Кога да използваме регулярни изрази. 487

Няколко думи за ефективността. 488

Няколко регулярни израза от практиката. 489

Размяна на първите две думи в низ. 489

Парсване на декларации <var>=<value>.. 489

Парсване на дати. 490

Премахване на път от името на файл. 491

Валидация на IP адреси. 491

Полезни Интернет ресурси. 491

Инструментът The Regulator 492

Упражнения. 496

Използвана литература. 497

Глава 11. Вход и изход. 499

Необходими знания. 499

Съдържание. 499

В тази тема ... 499

Какво представляват потоците? 500

Потоци – пример. 500

Потоците в .NET Framework. 501

Базови потоци (base streams) 502

Преходни потоци (pass-through streams) 502

Основни операции с потоци. 502

Типът System.IO.Stream.. 503

Четене от поток. 503

Писане в поток. 504

Изчистване на работните буфери. 505

Затваряне на поток. 505

Промяна на текущата позиция в поток. 506

Буферирани потоци. 506

Файлови потоци. 507

Създаване на файлове поток. 507

Четене и писане във файлов поток. 508

Пример – замяна на стойност в двоичен файл. 508

Четци и писачи. 509

Двоични четци и писачи. 509

Текстови четци и писачи. 511

Четци, писачи и кодирания. 515

Потоци в паметта. 515

Четене от MemoryStream – пример. 515

Писане в MemoryStream – пример. 516

Операции с файлове. Класове File и FileInfo. 517

File и FileInfo – пример. 517

Работа с директории. Класове Directory и DirectoryInfo. 518

Рекурсивно обхождане на директории – пример. 518

Класът Path. 520

Специални директории. 521

Наблюдение на файловата система. 522

Наблюдение на файловата система – пример. 522

Как работи примерът?. 523

Работа с IsolatedStorage. 524

IsolatedStorage – пример. 525

Упражнения. 526

Използвана литература. 528

Глава 12. Работа с XML. 529

Необходими знания. 529

Съдържание. 529

В тази тема... 529

Какво е XML? 531

XML (Extensible Markup Language) 531

Какво представлява един markup език?. 531

XML markup – пример. 531

Универсална нотация за описание на структурирани данни. 532

XML съдържа метаинформация за данните. 532

XML е метаезик. 532

XML е световно утвърден стандарт. 532

XML е независим. 532

XML – пример. 532

XML и HTML 533

Прилики между езиците XML и HTML. 533

Разлики между езиците XML и HTML. 533

Добре дефинирани документи. 534

XML изисква добре дефинирани документи. 534

Пример за лошо дефиниран XML документ. 534

Кога се използва XML? 535

Обмяна на информация. 535

Съхранение на структурирани данни. 535

Недостатъци на XML 535

Обемисти данни. 536

Повишена необходимост от физическа памет. 536

Намалена производителност. 536

Пространства от имена. 536

Дефиниране на пространства от имена. 537

Използване на тагове с еднакви имена – пример. 537

Пространства по подразбиране. 538

Пространства по подразбиране – пример. 538

Пространства от имена и пространства по подразбиране – пример. 539

Схеми и валидация. 539

XML схеми – защо са необходими?. 540

XML схеми – видове. 540

Езикът DTD. 540

XSD схеми. 542

XDR схеми. 544

Редакторът за схеми на VS.NET. 547

XML парсери. 551

XML парсери – приложение. 552

XML парсери – видове. 552

DOM.. 552

SAX. 553

XML и .NET Framework. 554

.NET притежава вградена XML поддръжка. 554

.NET и DOM моделът. 554

Парсване на XML документ с DOM – пример. 555

Класовете за работа с DOM. 557

Класът XmlNode. 557

Класът XmlDocument 559

Промяна на XML документ с DOM – пример. 559

Построяване на XML документ с DOM – пример. 562

SAX парсери и XmlReader 563

Класът XmlReader 563

Разлика между pull и push парсер моделите. 563

Push парсер. 563

Pull парсер. 563

XmlReader – основни методи и свойства. 564

Класът XmlReader – начин на употреба. 564

XmlReader – пример. 564

Кога да използваме DOM и SAX? 566

Класът XmlWriter 566

XmlWriter – основни методи. 567

Работа с XmlWriter 567

XmlWriter – пример. 568

Валидация на XML по схема. 571

Класът XmlValidatingReader 571

XmlValidatingReader – основни методи, свойства и събития. 572

Валидация на XML – пример. 573

Валидация на XML при DOM.. 578

XPath. 579

Описание на езика. 579

XPath в .NET Framework. 582

XSLT. 591

Технологията XSLT. 591

XSLT и .NET Framework. 593

Упражнения. 597

Използвана литература. 599

Глава 13. Релационни бази от данни и MS SQL Server. 601

Необходими знания. 601

Съдържание. 601

В тази тема ... 602

Релационни бази от данни. 603

Модели на базите от данни. 603

Системи за управление на БД. 604

Таблици. 606

Схема на таблица. 606

Първичен ключ. 607

Външен ключ. 607

Връзки (релации) 607

Множественост на връзките. 608

Релационна схема. 609

Нормализация. 612

Ограничения (Constraints) 616

Индекси. 616

Езикът SQL. 617

Изгледи (Views) 617

Съхранени процедури (stored procedures) 619

Тригери (Triggers) 620

Транзакции. 621

Въведение в SQL Server 626

История на SQL Server 627

Системни компоненти на SQL Server 2000. 627

Програмиране за SQL Server 2000. 629

Въведение в T-SQL. 632

Data Definition Language (DDL) 632

Data Manipulation Language (DML) 636

DBCC команди в SQL Server 648

Съхранени процедури. 650

Транзакции в SQL Server 654

Пренасяне на база от данни. 660

Упражнения. 664

Използвана литература. 666

Глава 14. Достъп до данни с ADO.NET. 667

Необходими знания. 667

Съдържание. 667

В тази тема ... 668

Модели за работа с данни в ADO.NET. 669

Свързан модел (connected model) 669

Несвързан модел (disconnected model) 671

Еволюция на приложенията. 673

Еднослойни приложения. 673

Двуслойни приложения (клиент-сървър) 673

Трислойни приложения. 675

Многослойни приложения. 677

Какво е ADO.NET? 678

Пространства от имена на ADO.NET. 678

Еволюция на ADO към ADO.NET. 679

Компоненти на ADO.NET. 680

Доставчици на данни (Data Providers) в ADO.NET. 681

Стандартни доставчици на данни в ADO.NET. 683

Компоненти за работа в несвързана среда. 684

SqlClient Data Provider 684

Видове автентикация в SQL Server 2000. 685

Символен низ за връзка към база от данни (Connection String) 685

Connection Pooling. 687

Реализация на свързан модел в ADO.NET. 688

Кога да използваме свързан модел?. 688

Свързан модел от гледна точка на програмиста. 688

Класовете в свързана среда. 689

Класът SqlConnection. 690

Експлицитно отваряне и затваряне на връзка. 690

Имплицитно отваряне и затваряне на връзка. 691

Използване на метода Dispose() 691

Събитията на SqlConnection. 691

Класът SqlCommand. 694

По-важни свойства на SqlCommand. 694

По-важни методи на SqlCommand. 694

Класът SqlDataReader 695

По-важни методи и свойства на SqlDataReader 695

Свързан модел – пример. 696

Описание на примера. 697

Създаване на SqlCommand. 698

Създаване на SqlCommand чрез Server Explorer 698

Създаване на SqlCommand чрез Toolbox. 698

Параметрични SQL заявки. 700

Необходимост от параметрични заявки. 700

Класът SqlParameter 702

Параметрични заявки – пример. 703

Първичен ключ с пореден номер – извличане. 705

Използване на транзакции. 706

Работа с транзакции в SQL Server 706

Работа с транзакции в ADO.NET. 707

Транзакции – пример. 708

Връзка с други бази от данни. 710

OLE DB Data Provider 711

Стандартът OLE DB. 711

Връзка към OLE DB. 712

Връзка с OLE DB – пример. 712

Правилна работа с дати. 715

Работа с дати – пример. 716

Описание на примера. 718

Работа с картинки в база от данни. 719

Двоични данни в MS SQL Server 719

Двоични данни в Oracle. 719

Двоични данни в MS Access. 719

Съхранение на графични обекти – пример. 719

Как работи примерът?. 723

Работа с големи обеми двоични данни. 725

Четене на обемни данни. 725

Запис на обемни данни. 725

ADO.NET в несвързана среда. 725

Типични сценарии за работа в несвързана среда. 726

Несвързан модел в ADO.NET, XML и уеб услуги. 727

Класове за достъп до данните в несвързана среда. 728

DataSet – обектен модел. 729

Колекции в DataSet 729

Схема на DataSet 729

Силно типизирани DataSets. 730

Създаване на DataSet 731

Поддръжка на автоматично свързване. 736

Класът DataTable. 736

DataTable поддържа списък на всички промени. 737

Основни свойства на DataTable. 737

Основни методи на DataTable. 738

Работа с DataTable. 738

Използване на ограничения (constraints) 743

Първичен ключ. 743

ForeignKey и Unique ограничения. 743

Потребителски изрази. 745

Пример за дефиниране на колона чрез израз. 745

DataRelation обекти. 746

Релации и ограничения. 746

Релации и потребителски интерфейс. 747

Релации и потребителски изрази. 747

Основни методи, използващи релации. 747

Класът DataView. 748

Филтриране чрез израз. 748

Филтриране по версията на данните. 749

Сортиране по колона (колони) 749

Запазване и зареждане на данните от DataSet 750

DataSet.ReadXml() 750

DataSet.WriteXml() 751

ReadXml() и WriteXml() – пример. 752

Използване на DataAdapter 754

Архитектура на класа DataAdapter 754

Адаптерни класове за различните доставчици. 755

Създаване на DataAdapter 755

Методът Fill() на класа DataAdapter 756

Свойството MissingSchemaAction. 757

Запълване на няколко таблици. 757

Задаване на съответствие за таблици и колони. 758

Извличане на информация за схемата на източника. 759

Свойства AcceptChangesDuringFill и ContinueUpdateOnError 759

Събития на DataAdapter 760

Обновяване на данните в източника. 760

Класът CommandBuilder 761

Потребителска логика за обновяване на източника. 763

Извличане на обновени стойности в DataSet 763

DataAdapter – пример. 764

Обновяване на свързани таблици. 767

DataSet.GetChanges() и DataSet.HasChanges() 767

Параметри на методите. 767

Какво правят двата метода?. 768

Кога да използваме GetChanges() и HasChanges()?. 768

DataSet.GetChanges() – пример. 769

Грешките в DataSet и DataTable обектите. 769

Несвързан модел – типичен сценарий на работа. 770

Реализация на несвързан модел с DataSet и DataAdapter – пример. 771

Класът XmlDataDocument 777

Предимства на XmlDataDocument 777

Начини за синхронизация. 777

XmlDataDocment – пример. 778

Сигурността при работа с бази от данни. 780

Сигурност при динамични SQL заявки. 780

Connection pooling и сигурност. 780

Съхраняване на connection string. 780

Защитна стена. 781

Криптиране на комуникацията. 781

Упражнения. 781

Използвана литература. 784

Том 2

Глава 15. Графичен потребителски интерфейс с Windows Forms. 785

Глава 16. Изграждане на уеб приложения с ASP.NET. 786

Глава 17. Многонишково програмиране и синхронизация. 787

Глава 18. Мрежово и Интернет програмиране. 788

Глава 19. Отражение на типовете (Reflection). 789

Глава 20. Сериализация на данни. 790

Глава 21. Уеб услуги с ASP.NET. 791

Глава 22. Отдалечено извикване на методи (Remoting). 792

Глава 23. Взаимодействие с неуправляван код. 793

Глава 24. Управление на паметта и ресурсите. 794

Глава 25. Асемблита и разпространение. 795

Глава 26. Сигурност в .NET Framework. 796

Глава 27. Mono - свободна имплементация на .NET. 797

Глава 28. Помощни инструменти за .NET разработчици. 798

Глава 29. Практически проект. 799

Заключение. 800

 


Национална академия по разработка на софтуер

Лекторите

» Светлин Наков е автор на десетки технически публи­ка­ции и ня­колко книги, свър­­зани с раз­работката на соф­ту­ер, заради което е тър­сен лектор и кон­султант.

Той е разработчик с дъл­гого­дишен опит, работил по раз­нообразни проекти, реали­зи­рани с раз­лични техноло­гии (.NET, Java, Oracle, PKI и др.) и преподавател по съвре­мен­ни софтуерни технологии в СУ "Св. Климент Охридски".

През 2004 г. е носител на награ­дата "Джон Атанасов" на прези­дента на България Ге­орги Пър­ва­нов.

Светлин Наков ръководи обу­чението по Java технологии в Академията.

 

» Мартин Кулов е софтуерен инженер и консул­тант с дългогодишен опит в изграждането на решения с платформите на Microsoft.

Мартин е опитен инструктор и сертифициран от Майкрософт разработчик по програмите MCSD, MCSD.NET, MCPD и MVP и меж­дународен лектор в световна­та организа­ция на .NET потре­бителски­те групи INETA.

Мартин Кулов ръководи обу­чението по .NET технологии в Академията.

Академията

» Национална академия по раз­ра­ботка на софтуер (НАРС) е център за професионално обу­чение на соф­ту­ерни специалисти.

 

» НАРС провежда БЕЗПЛАТНО кур­сове по разработка на софтуер и съв­ременни софтуерни тех­нологии в Со­фия и други градове.

 

» Предлагани специалности:

§  Въведение в програмирането (с езиците C# и Java)

§  Core .NET Developer

§  Core Java Developer

 

» Качествено обу­чение с много практически про­екти и индивиду­ално внимание за всеки.

 

» Гарантирана работа! Трудов до­говор при постъпване в Академията.

 

» БЕЗПЛАТНО!

Учите безплатно във въведителните курсове и по стипендии от работода­телите в следващите нива.

http://academy.devbg.org


Предговор

Ако по принцип не четете уводите на книгите, помислете преди да про­пуснете и този. Той е малко по-различен от всички останали, защото тази книга е също малко по-различна от всички останали.

Ако смятате, че ще ви досадим с общи приказки, можете да не се задъл­бо­ча­вате прекалено, но ви препоръчваме поне да преминете през следва­щите страници "по венти­латорната система", за да разберете какво ви предстои да научите от следващите страници. Ще разберете какво е .NET Framework, за какво служи, какви технологии обхваща и как настоящата книга от една идея се превърна в реалност.

Това е първата чисто българска книга за програмиране с .NET Framework и C#, но за сметка на това е една от най-полезните книги в тази област. Написана от специалисти с опит както в практическата работа с .NET, така и в обучението по програмиране, книгата ще ви даде не само основите на .NET програмирането, но и ще ви запознае с някои по-сложни концеп­ции и ще ви предаде от опита на авторите.

За кого е предназначена тази книга?

.NET Framework? Ама какво е това? Някаква нова измислица на Microsoft или просто поредния език за програмиране? Да не би да са направили нова версия на C++ или Java? A какъв е тоя език C#? Не мога ли да си пиша на C или C++? Какво е това среда за управлявано изпълнение на код? Не отмина ли вече времето на интерпретираните езици? Защо въобще трябва да сменяме добрите стари платформи с този .NET?

Ако нямате ясен отговор на всички тези въпроси, тази книга е за вас! Ако пък имате – тази книга също е за вас, защото едва ли знаете всичко за програмирането с .NET Framework и едва ли поз­навате добре всички по-важни технологии, свързани с него.

Тази книга ще ви даде много повече от начални знания. Тя ще ви предаде опит, натрупан в продъл­жение години, и ще ви запознае с утвър­дените практики при използването на .NET технологиите.

Тази книга е за всички, които искат да се научат да програмират с .NET Framework и C#, както и за всички, които вече имат основни знания и умения в областта, но искат да ги разширят и да навлязат в някои от по-сложните технологии, с които нямат достатъчно опит.

Книгата е полезна не само за .NET програмисти, но и за всички, които имат желание да се занимават сериозно с разработка на софтуер. В нея се обръща внимание не само на специфичните .NET технологии, но и на някои фундамен­тални концепции, които всеки програмист трябва добре да знае и разбира.

Необходими начални познания

Тази книга не е подходяща за хора, които никога не са програмирали в живота си. Ако сте абсолютно начинаещ, спрете да четете и просто започ­нете с друга книга!

В нея няма да намерите обяснения за това какво е променлива, какво е тип данни, какво е условна конструкция, какво е цикъл и какво е функ­ция. Очакваме читателят да е запознат добре с всички тези понятия и с основите на програмирането. Познанията по обектно-ориентирано програ­миране (ООП) също ще са полезни, тъй като в книгата не се изясняват в дълбочина теоретичните концепции на ООП, а само средствата за тяхното прилагане в езика C#.

Какво представлява .NET Framework?

.NET Framework е съвременна платформа за разработка и изпълнение на приложения. Тя предоставя програмен модел, стан­дартна библиотека от класове и среда за контролирано изпълнение на програмен код.

.NET Framework поддържа различни езици за програмиране и позволява тяхната съвместна работа. .NET приложенията се пишат на езици от висо­ко ниво (C#, VB.NET, Managed C++ и други) и се компилират до междинен език от ниско ниво, наречен IL (Intermediate Language). По време на изпълнение IL програмите (т. нар. управляван код) се компилират до инструкции за текущата хардуерна архитектура, съобразени с текущата операционна система, и след това се изпълняват от микропроцесора.

.NET Framework включва в себе си стандартна библиотека, която съдържа базова функционалност за разработка, необходима за пове­чето приложе­ния, като вход/изход, връзка с бази данни, работа с XML, изграждане на уеб приложения, използване на уеб услуги, изграждане на графичен пот­ребителски интерфейс и др.

Какво обхваща тази книга?

Програмирането за .NET Framework изисква познания на неговите базови концепции (модел на изпълнение на кода, обща система от типове, управ­ление на паметта, масиви, колекции, символни низове и др.), както и познаване на често използваните технологии – ADO.NET (за достъп до бази от данни), Windows Forms (за приложения с графичен потребителски интерфейс), ASP.NET (за уеб приложения и уеб услуги) и др.

Настоящата книга обхваща всички тези концепции и технологии, свързани с разработката на приложения за .NET Framework. Тя има за цел да запо­знае читателя с принципите на разработка на приложения за Microsoft .NET Framework и да даде широки познания по всички по-важни техноло­гии, свързани с него.

Най-важните теми, които ще бъдат разгледани, са: архитектура на .NET Framework, управлявана среда за изпълнение на код (CLR), езикът C# и реализация на обектно-ориентирано програмиране с неговите средства, обща система от типове (CTS), основна библиотека от класове (Framework Class Library), достъп до бази от данни с ADO.NET, работа с XML, създа­ване на графичен потребителски интерфейс с Windows Forms и уеб-бази­рани при­ложения с ASP.NET. Ще бъде обърнато внимание и на някои по-сложни концепции като отражение на типовете, сериализация, много­нишково програмиране, уеб услуги, отдалечено извикване на методи (remoting), взаимодей­ствие с неуправляван код, асемблита, управление на сигурността, по-важни инструменти за разработка и др. Ще бъде разгледана и свободната имплементация на .NET Framework за Linux и други операци­онни системи (Mono). Накрая ще бъде описана разра­ботката на един цялостен практически проект, който обхваща всички по-важни технологии и демонстрира добрите прак­тики при изграждането на .NET приложения.

Фокусът е върху .NET Framework 1.1

Всички теми са базирани на .NET Framework 1.1, Visual Studio .NET 2003 и MS SQL Server 2000. Не се обръща много внимание на новостите в .NET Framework 2.0, Visual Studio 2005 и SQL Server 2005, тъй като по време на разработката на книгата тези продукти и технологии все още не бяха официално излезли на пазара и тяхното бъдеще не беше съвсем ясно.

Въпреки предстоящото излизане на .NET Framework 2.0, настоящата книга си остава изключително полезна, тъй като в същината си версия 2.0 не носи фундаментални промени, а по-скоро разширява вече съществува­щи­те технологии, които ще разгледаме в книгата.

Как е представена информацията?

Въпреки големия брой автори, съавтори и редактори, стилът на текста в книгата е изключително достъпен. Съдържанието е представено в добре структуриран вид, разделено с множество заглавия и подзаглавия, което позволява лесното му възприемане, както и бързото търсене на инфор­мация в текста.

Настоящата книга е написана от програмисти за програмисти. Авто­рите са действащи софтуерни разработчици, хора с реален опит както в разра­ботването на софтуер, така и в обучението по програмиране. Благо­даре­ние на това качеството на изложението е на мно­го високо ниво.

Всички автори ясно съзнават, че примерният сорс код е едно от най-важните неща в една книга за програ­ми­ране. Именно поради тази причи­на текстът е съпроводен с много, много примери, илюстрации и картинки.

Въобще някой чете ли текста, когато има добър и ясен пример? Повечето програмисти първо гледат дали примерът ще им свърши работа, и само ако нещо не е ясно, се зачитат в текста (това всъщност не е никак добра практика, но такава е реалността). Ето защо многото и добре подбрани примери са един от най-важните принципи, залегнали в тази книга.

Защо C#?

Всички примери в книгата са написани на езика C#, въпреки, че .NET Framework поддържа много други езици. Този избор е направен по ня­колко причини:

-     C# е препоръчваният език за програмиране за .NET Framework. Архитектите на езика специално са го проектирали за .NET Framework и са го съобразили с особеностите на платформата още по време на дизайна. C# наследява простотата на Java, мощността на C++ и силните черти на Delphi. Той притежава максимално стегнат и ясен синтаксис.

-     В България C# е най-популярният от .NET езиците и се използва най-масово в българските софтуерни компании.

-     C# е от семейството на C-базираните езици и синтактично много прилича на Java, C++, C и PHP.  Много хора, които не знаят езика, биха разбрали при­мерите без особени усилия.

-     За C# има повече статии в специализираните сайтове и лични днев­ници (blogs) в Интернет. Общността на C# разработчиците е по-добре развита, отколкото на разработчиците на другите .NET езици.

-     Поради голямата популярност на езика C# за него има по-добра поддръжка от инструментите за разработка.

-     Езици като C++, Visual Basic и JScript не са проектирани специално за .NET Framework, а са адаптирани допълнително към него чрез редица изменения и добавки. В следствие на това те запазват някои синтактични особе­ности, които не са удобни при работата с .NET.

Ако сега започвате да изучавате .NET Framework, Ви препоръчваме да стартирате от езика C#. След като го овладеете, можете да опитате и другите .NET езици, но за начало C# е най-подходящ.

По принцип езикът C++ може да се използва при програмиране с .NET Framework, но това се препоръчва само при някои много специфични приложения. Този език по първоначален замисъл не е проектиран за .NET платформата и има съвсем друго пред­назна­чение. Той е много по-сложен и труден от C# и затова е по-добре да използвате C#, дори ако трябва да го учите от начало. Ако вече знаете C++, няма да ви е трудно да овладеете C# и когато го направите, ще се убедите, че с него се работи много по-лесно.

Въпреки, че езикът Visual Basic .NET (VB.NET) има някои предимства и се използва масово по света, за предпочитане е да ползвате C# при изграж­дане на .NET приложения. Езикът Visual Basic е масово разпро­странен по истори­чески причини (благодарение най-вече на Бил Гейтс). Някои специ­алисти изказват силно негативни мнения срещу BASIC и произлизащите от него езици, докато други (включително и Microsoft) го подкрепят и препо­ръч­ват.

Ще си позволим да цитираме изказването на един от най-извест­ните учени в областта на компютърните науки проф. д-р Едсгар Дейкстра за езика BASIC, от който произлиза VB.NET:

Практически е невъзможно да научиш на добро програми­ране студенти, които са имали предишен досег до езика BASIC – като потенциални програмисти, те са мисловно осакатени, без надежда за възстановяване.

Едсгар Дейкстра

Горният цитат се отнася за старите версии на езика BASIC. VB.NET е вече съвременен обектно-ориентиран език, който не отстъпва по нищо на C#, освен че има малко по-нетрадиционен синтаксис (в сравнение със семей­ството на C-базираните езици).

.NET Framework позволява всеки да програмира на любимия си език. Изборът си е лично ваш. Ние можем само да ви дадем препоръки. За цели­те на настоящата книга автор­ският колектив е избрал езика C# и препо­ръчва на читателите да започнат от него.

Поглед към съдържанието на книгата

Книгата се състои от 29 глави, които поради големия обем са разделени в два тома. Том 1 съдържа първите 14 глави, а том 2 – остана­лите 15. Това важи само за хартиеното издание на книгата. В електронния вариант тя се разпространява като едно цяло.

Нека направим кратък преглед на всяка една от главите и да се запознаем с нейното съдържание, за да разберем какво ни очаква по-нататък.

Глава 1. Архитектура на .NET Framework

В глава 1 е представена платформата .NET, която въплъщава визията на Microsoft за развитието на информаци­онните и соф­туерните техноло­гии, след което е разгледана средата за разработка и изпълне­ние на .NET при­ложения Microsoft .NET Framework.

Обръща се внимание на управля­вания код, на езика IL, на общата среда за контроли­рано изпълнение на управляван код (Common Language Runtime) и на модела на компилация и изпълнение на .NET кода. Раз­глеждат се още Common Language Specification (CLS), Common Type System (CTS), Common Language Infrastructure (CLI), интеграцията на различни езици, библиоте­ката от класове Framework Class Library и интегрираната среда за разра­ботка Visual Studio .NET.

Автори на главата са Виктор Живков и Николай Недялков. Текстът е напи­сан с широко използване на лекциите на Светлин Наков по темата и е редак­тиран от Иван Митев и Светлин Наков.

Глава 2. Въведение в езика C#

Глава 2 разглежда езика С#, неговия синтаксис и основни концепции. Представя се средата за разработка Visual Studio .NET 2003 и се демон­стрира работата с нейния дебъгер. Отделя се внимание на типове­те дан­ни, изразите, програм­ните конструкции и конструкциите за управ­ле­ние в езика C#. Накрая се демонстри­ра колко лесно и полезно е XML доку­ментирането на кода в С#.

Автор на главата е Моника Алексиева. Текстът е базиран на лекцията на Светлин Наков по същата тема и е редак­тиран от Панайот Добриков и Преслав Наков.

Глава 3. Обектно-ориентирано програмиране в .NET

В глава 3 се прави кратък обзор на основните принципи на обектно-ориентираното програмиране (ООП) и сред­ствата за изпол­зването им в .NET Framework и езика C#. Представят се типовете "клас", "струк­тура" и "интерфейс" в C#. Въвежда се понятието "член на тип" и се разглеждат видовете членове (член-променливи, методи, конструктори, свойства, индексатори и др.) и тяхната употреба. Разглежда се насле­дяването на ти­по­ве в различните му аспекти и приложения. Обръща се внимание и на полиморфизма в C# и свързаните с него понятия и прог­рамни техники. Накрая се дискутират някои утвър­дени практики при създа­ването на ефек­тив­ни йерархии от типове.

Автор на главата е Стефан Кирязов. Текстът е написан с широко изпол­зване на лекции на Светлин Наков и е редак­тиран от Цветелин Андреев и Панайот Добриков.

Глава 4. Обработка на изключения в .NET

В глава 4 се разглеждат изключенията в .NET Framework като утвърден механизъм за управление на грешки и непредвидени ситуации. Дават се обяснения как се прихващат и обработват изключения. Разглеждат се начините за тяхното преди­звикване и различните видове изключе­ния в .NET Framework. Дават се примери за дефиниране на соб­ствени (потреби­телски) изключения.

Автори на главата са Явор Ташев и Светлин Наков. Текстът е написан с широко изпол­зване на лекции на Светлин Наков по темата. Редактор е Мартин Кулов.

Глава 5. Обща система от типове

В глава 5 се разглежда общата система от типове (Common Type System) в .NET Framework. Обръ­ща се внимание на разликата между стойностни и референтни типо­ве, разгле­жда се основополагащият тип System.Object и йерархията на типо­вете, про­излизаща от него. Дискутират се и някои особености при работа с типове – преобразуване към друг тип, проверка на тип, клони­ране, опа­коване, разопаковане и др.

Автор на главата е Светлин Наков. Текстът е базиран изцяло на лекцията на Светлин Наков по същата тема и е редактиран от Преслав Наков и Панайот Добриков.

Глава 6. Делегати и събития

В глава 6 се разглежда референтният тип "делегат". Илюстрирани се начи­ните за неговото използване, различните видове деле­гати, както и негови харак­терни приложения. Представя се понятието "събитие" и се обяснява връзката му с делегатите. Прави се сравнение между делегатите и интер­фей­сите и се дават препоръки в кои случаи да се използват едните и в кои – другите.

Автор на главата е Лазар Кирчев. Текстът е базиран на лекцията на Светлин Наков по същата тема.

Глава 7. Атрибути

В глава 7 се разглежда какво представляват атрибутите в .NET Framework, как се прилагат и къде се използват. Дават се обяснения как можем да дефинираме собствени атрибути и да извличаме приложе­ните атрибути от метаданните на асемблитата.

Автори на главата са Преслав Наков и Панайот Добриков. Текстът е бази­ран основно на лекцията на Светлин Наков по същата тема и е редактиран от него.

Глава 8. Масиви и колекции

В глава 8 се представят масивите и колекциите в .NET Framework. Раз­глеждат се видовете масиви – едномерни, многомерни и масиви от масиви (т. нар. назъбени масиви), както и базовият за всички масиви тип System. Array. Дискутират се начините за сортиране на масиви и търсене в тях. Разглеждат се колекциите и тяхната реализация в .NET Framework, класо­вете ArrayList, Queue, Stack, Hashtable и SortedList, както и интерфей­сите, които те имплементират.

Автори на главата са Стефан Добрев и Деян Варчев. Текстът е базиран на лекцията на Светлин Наков по същата тема и е редактиран от него.

Глава 9. Символни низове

В глава 9 се разглежда начинът на представяне на символните низове в .NET Framework и методите за работа с тях. Обръща се внимание на кодира­щите схеми, които се използват при съхраняване и пренос на тек­стова информация. Разглеждат се подробно различните начини за манипу­ли­ра­не на низове, както и някои практически съобра­жения при работата с тях. Демонстрира се как настройките за държава и регион (култура) опре­делят вида на текста, показван на потребителите, и как можем да форма­тираме изхода в четлив и приемлив вид. Разглеждат се също и начините за прео­бразуване на вход от потребителя от текст в обект от стандартен тип, с който можем лесно да работим.

Автори на главата са Васил Бакалов и Александър Хаджикръстев. В текста е широко използвана лекцията на Светлин Наков по същата тема. Главата е редактирана от Иван Митев.

Глава 10. Регулярни изрази

В глава 10 се разглеждат регулярните изрази, набиращи все по-голяма популярност сред разработчиците на софтуер при решаването на пробле­ми, свързани с обработката на текст. Дискутират се произходът и същ­ността на регулярните изрази, техният синтаксис и основ­ните правила при конструирането им. В главата е предложено кратко предста­вяне на основ­ните дейности, при които е подходящо използването на регулярни изрази, и са дадени конкретни насоки как можем да правим това със средствата на .NET Framework. Разглежда се инструментариу­мът, за работа с регу­лярни изра­зи, който стандартната библиотека с класове предоста­вя, и се описват най-важните методи, съпроводени с достатъчно примери.

Автор на главата е Георги Пенчев. При изготвянето на текста е частично използвана лекцията на Светлин Наков по темата. Технически редактор е Иван Митев.

Глава 11. Вход/изход

В глава 11 се разглежда начинът, по който се осъществяват вход и изход от дадена програма в .NET Framework. Представят се различните видове по­тоци – абстракцията, която позволява връзката на програмата с някак­во устройство за съхранение на данни. Обяснява се работата на четците и писачите, които обвиват потоците и така улесняват тяхното използване. Накрая, се прави преглед на средствата, които .NET Framework предос­тавя за работа с файлове и директории и за наблюдение на файловата система.

Автор на главата е Александър Русев. Текстът е базиран на лекцията на Светлин Наков по същата тема и е редактиран от Галин Илиев и Светлин Наков.

Глава 12. Работа с XML

В глава 12 се разглежда работата с XML в .NET Framework. Обяснява се накратко какво представлява езикът XML. Обръща се внимание на при­ликите и разликите между него и HTML. Разглеждат се приложе­нията на XML, пространствата от имена и различните схеми за валидация на XML документи (DTD, XSD, XDR). Пред­ставят се средствата на Visual Studio .NET за работа с XSD схеми. Разглеждат се особеностите на класическите XML парсери (DOM и SAX) и как те са имплементирани в .NET Framework. Описват се подробно класовете за работа с DOM парсера (XmlNode и XmlDocument) и ролята на класа XmlReader при SAX парсерите в .NET Framework. Обръща се внимание на начина на работа на класа XmlWriter за създаване на XML документи. Дискутират се начините за валидация на XML документи спрямо дадена схема. Разглежда се поддръжката в .NET Framework и на някои други XML-базирани техноло­гии като XPath и XSLT.

Автор на главата е Манол Донев, а редактори са Иван Митев и Светлин Наков. Текстът широко използва лекцията на Светлин Наков по същата тема.

Глава 13. Релационни бази от данни и MS SQL Server

В глава 13 се разглеждат системите за управление на релаци­онни бази от данни. Обясняват се свързаните с тях понятия като таблици, връзки, ре­ла­ционна схема, нормализация, изгледи, ограни­чения, транзак­ции, съхра­нени проце­дури и тригери. Прави се кратък преглед на езика SQL, изпол­зван за манипулиране на релационни бази от данни.

След въведението в проблематиката на релационните бази от данни се прави кратък преглед на Microsoft SQL Server, като типичен пред­ста­вител на RDBMS сървърите. Разглеждат се неговите основ­ни компоненти и инстру­менти за управление. Представя се използваното от него разшире­ние на езика SQL, наречено T-SQL, и се дискутират основ­ните DDL, DML и DBCC команди. Обръща се внимание на съхранените проце­дури в SQL Server и се обяснява как той под­държа някои важни характе­рис­тики на една релационна база от данни, като транзакции, нива на изолация и др.

Автор на главата е Стефан Захариев. В текста са използвани учебни мате­риали от Бранимир Гюров, Светлин Наков и Стефан Захариев. Редак­тор е Светлин Наков.

Глава 14. ADO.NET и работа с данни

В глава 14 се разгледат подробно двата модела за достъп до данни, реализирани в ADO.NET – свързан и несвързан. Опи­сва се прог­рамният модел на ADO.NET, неговите компоненти и доставчиците на данни. Обяс­нява се кои класове се изпол­зват за свързан достъп до данни, и кои – за несвързан.

При разглеждането на свързания модел за достъп до данни се обръща внимание на доставчикa на данни SqlClient за връзка с MS SQL Server и се обяснява как се използват класовете SqlConnection, SqlCommand и SqlDataReader. Разглежда се работата с параметризирани заявки и изпол­зването на транзакции от ADO.NET. Дава се пример за достъп и до други бази от данни през OLE DB. Разглеждат се и някои проблеми при работа с дати и съхранение на графични изображения в базата данни.

При разглеждането на несвързания модел за достъп до данни се диску­тират в детайли основните ADO.NET класове за неговата реали­зацияDataSet и DataTable. Дават се примери и обяснения как се използват ограничения, изрази, релации и изгледи в обектния модел DataSet. Обръща се специално внимание на класа DataAdapter и вариантите за неговото използване при зареждане на данни и обновяване на базата от данни. Разглеждат се подходите за ре­шаване на конфликти при нанасяне на промени в базата данни. Дискутират се и начините за връзка между ADO.NET и XML, а накрая се разглеждат проблемите със сигурността в приложе­нията, използващи бази от данни.

Автори на главата са Христо Радков (частта за свързания модел) и Лазар Кирчев (частта за несвързания модел). Гла­вата е разра­ботена с широко използване на лекцията на Бранимир Гюров и Светлин Наков по същата тема. Редактори са Светлин Наков и Мартин Кулов.

Глава 15. Графичен потребителски интерфейс с Windows Forms

В глава 15 се разглеждат средствата на Windows Forms за създаване на прозоречно-базиран графичен потребителски интерфейс (GUI) за .NET приложенията. Представят се програмният модел на Windows Forms, него­вите базови контроли, средствата за създаване на прозорци, диалози, менюта, ленти с инструменти и статус ленти, както и някои по-сложни концепции като: MDI приложения, data-binding, наследяване на форми, хос­тинг на контроли в Internet Explorer, работа с нишки във Windows Forms и др.

Автори на главата са Радослав Иванов (по-голямата част) и Светлин Наков. Текстът е базиран на лекцията на Светлин Наков по същата тема.

Глава 16. Изграждане на уеб приложения с ASP.NET

В глава 16 се разглежда разработката на уеб приложения с ASP.NET. Представят се програмният модел на ASP.NET, уеб формите, кодът зад тях, жизненият цикъл на уеб приложенията, различните типове контроли и техните събития. Показва се как се дебъгват и проследяват уеб прило­жения. Отделя се внимание на валидацията на данни, въведени от потре­бителя. Разглежда се концепцията за управление на състоянието на обек­тите – View State и Session State. Демонстрира се как могат да се визуа­лизират и редактират данни, съхранявани в база от данни. Диску­тират се разгръщането и конфигурирането на ASP.NET уеб приложе­нията в Internet Information Server (IIS) и сигур­ността при уеб приложенията.

Автор на главата е Михаил Стойнов. Текстът е базиран на лекцията на Михаил Стойнов по същата тема.

Глава 17. Многонишково програмиране и синхронизация

В глава 17 се разглежда многозадачността в съвременните опе­рационни системи и средствата за паралелно изпълнение на програ­мен код, които .NET Framework предоставя. Обръща се внимание на ниш­ките (threads), техните състояния и управлението на техния жизнен цикъл – стартиране, приспиване, събуждане, прекратяване и др.

Разглеждат средствата за синхронизация на нишки при достъп до общи данни, както и начините за изчакване на зает ресурс и нотификация при освобождаване на ресурс. Обръща се внимание както на синхронизацион­ните обекти в .NET Framework, така и на неуправляваните синхронизаци­онни обекти от операционната система.

Изяснява се концепцията за работа с вградения в .NET Framework пул от нишки (thread pool), начините за асинхронно изпълнение на задачи, сред­ствата за контрол над тяхното поведение и препоръчваните практики за работа с тях.

Автор на главата е Александър Русев. Текстът е базиран в голямата си част на лекцията на Михаил Стойнов и авторските бележки в нея.

Глава 18. Мрежово и Интернет програмиране

В глава 18 се разглеждат някои основни средства, предлагани от .NET Framework за мрежово програмиране. Главата започва със съвсем кратко въведение в прин­ципите на работа на съвременните компютърни мрежи и на Интернет и продължава с протоколите, чрез които се осъществява мре­жовата комуни­кация. Обект на дискусия са както класовете за работа с TCP и UDP сокети, така и някои класове, предлагащи по-специфични въз­можности, като представяне на IP адреси, изпълняване на DNS заявки и др. В края на главата ще се представят средствата за извли­чане на уеб-ресурси от Интернет и на класовете за работа с e-mail в .NET Framework.

Автори на главата са Ивайло Христов и Георги Пенчев. Текстът широко използва лекцията на Ивайло Христов по същата тема.

Глава 19. Отражение на типовете (Reflection)

В глава 19 се представя понятието Global Assembly Cache (GAC) и отра­жение на типовете (reflection). Разглеждат се начините за зареждане на асембли. Демонстрира се как може да се извлече информация за типове­те в дадено асембли и за членовете на даден тип. Разглеждат се начини за динамич­но извикване на членове от даден тип. Обяснява се как може да се създаде едно асембли, да се дефинират типове в него и асемблито да се запише във файл по време на изпълнение на програмата.

Автор на главата е Димитър Канев. Текстът е базиран на лекцията на Ивайло Христов по същата тема. Редактор е Светлин Наков.

Глава 20. Сериализация на данни

В глава 20 се разглежда сериализацията на данни в .NET Framework. Обяснява се какво е сериализация, за какво се използва и как се контро­ли­ра процесът на сериализация. Разглеждат се видовете форматери (formatters). Обяснява се какво е XML сериализация, как работи тя и как може да се контролира изходният XML при нейното използване.

Автор на главата е Радослав Иванов. Текстът е базиран на лекцията на Михаил Стойнов по същата тема. Редактор е Светлин Наков.

Глава 21. Уеб услуги с ASP.NET

В глава 21 се разглеждат уеб услугите, тяхното изграждане и консумация чрез ASP.NET и .NET Framework. Обект на дискусия са основните техноло­гии, свързани с уеб услу­гите, и причината те да се превърнат в стандарт за интеграция и между­плат­формена комуникация. Представят се различни сценарии за изпол­зването им. Разглежда се програмният модел за уеб услуги в ASP.NET и сред­ствата за тяхното изграждане, изпълнение и раз­гръщане (deployment). Накрая се дискутират някои често срещани проблеми и утвърдени практики при разработката на уеб услуги чрез .NET Framework.

Автори на главата са Стефан Добрев и Деян Варчев. В текста са изпол­звани материали от лекцията на Светлин Наков по същата тема. Техни­чески редактор е Мартин Кулов.

Глава 22. Отдалечено извикване на методи (Remoting)

В глава 22 се разглежда инфраструктурата за отдалечени извик­вания, която .NET Framework предоставя на разработчиците. Обясняват се осно­вите на Remoting технологията и всеки един от нейните компо­ненти: канали, форматери, отдалече­ни обекти и активация. Дискутират се разли­ките между различните типове отдалечени обекти. Обясняват се техният жизнен цикъл и видовете маршали­зация. Стъпка по стъпка се достига до създаването на приме­рен Remoting сървър и клиент. Накрая се представя един гъвкав и практичен начин за конфигуриране на цялата Remoting инфраструктура чрез конфигурационни файлове.

Автор на главата е Виктор Живков. В текста са използвани материали от лекцията на Светлин Наков. Редактори са Иван Митев и Светлин Наков.

Глава 23. Взаимодействие с неуправляван код

Глава 23 разглежда как можем да разширим възможностите на .NET Framework чрез употреба на предоставените от Windows приложни прог­рамни интер­фейси (API). Дискутират се средствата за извикване на функ­ци­оналност от динамични Win32 библиотеки и на проблемите с прео­бразу­ва­нето (маршализацията) между Win32 и .NET типовете.

Обръща се внимание на връзката между .NET Framework и COM (компо­нентният модел на Windows). Разглеждат се както извикването на COM обекти от .NET код, така и разкриването на .NET компонент като COM обект. Демонстрира се и технологията IJW за използване на неуправляван код от програми, написани на Managed C++.

Автор на главата е Мартин Кулов. Текстът е базиран на неговата лекция по същата тема. Технически редактор е Галин Илиев.

Глава 24. Управление на паметта и ресурсите

В глава 24 се разглежда писането на правилен и ефективен код по отно­шение използването на паметта и ресурсите в .NET Framework. В началото се прави сравнение на предимствата и недостатъците на ръчното и авто­матичното управление на памет и ресурси. След това се разглежда по-обстойно авто­матич­ното им управление с фокус най-вече върху системата за почистване на паметта в .NET (т. нар. garbage collector). Обръща се внимание на взаимо­действието с нея и практиките, с които можем да й помогнем да работи възможно най-ефективно.

Автори на главата са Стоян Дамов и Димитър Бонев. Технически редактор е Светлин Наков.

Глава 25. Асемблита и разпространение (deployment)

В глава 25 се разглежда най-малката съставна част на .NET приложе­нията – асембли, различните техники за разпространение на готовия соф­туерен продукт на клиентските работни станции и някои избрани техники за създаване на инсталационни пакети и капаните, за които трябва да се внимава при създаване на инсталационни пакети.

Автор на тази глава е Галин Илиев. В текста е използвана частично лекцията на Михаил Стойнов. Технически редактор е Светлин Наков.

Глава 26. Сигурност в .NET Framework

В глава 26 се разглежда как .NET Framework подпомага сигурността на създаваните приложения. Това включва както безопасност на типовете и защита на паметта, така и средствата за защита от изпъл­нение на неже­лан код, автентикация и оторизация, електронен подпис и криптогра­фия. Разглеждат се технологиите на .NET Framework като Code Access Security, Role-Based Security, силно-именувани асемблита, цифрово подписване на XML документи (XMLDSIG) и други.

Автори на главата са Тодор Колев и Васил Бакалов. В текста е широко използвана лекцията на Светлин Наков по същата тема. Технически редактор е Светлин Наков.

Глава 27. Mono - свободна имплементация на .NET

В глава 27 се разглежда една от алтернативите на Microsoft .NET Framework – проектът с отворен код Mono. Обясняват се накратко начи­ните за инсталиране и работа с Mono, използването на вградените техно­логии ASP.NET и ADO.NET, както и създаването на графични приложения. Дават се и няколко съвети и препоръки за писането на преносим код.

Автори на главата са Цветелин Андреев и Антон Андреев. Текстът е бази­ран на лекцията на Антон Андреев по същата тема. Технически редактор е Светлин Наков. Коректор е Соня Бибиликова.

Глава 28. Помощни инструменти за .NET разработчици

В глава 28 се разглеждат редица инструменти, използвани при разработ­ката на .NET приложения. С тяхна помощ може значително да се улесни изпълнението на някои често срещани програмистки задачи. Изброените инструменти помагат за повишаване качеството на кода, за увеличаване продуктивността на разработка и за избягване на някои традиционни трудности при поддръжката. Разглеждат се в детайли инструментите .NET Reflector, FxCop, CodeSmith, NUnit (заедно с допълненията към него NMock, NUnitAsp и NUnitForms), log4net, NHibernate и NAnt.

Автори на главата са Иван Митев и Христо Дешев. Текстът е по техни авторски материали. Редактор е Светлин Наков.

Глава 29. Практически проект

В глава 29 се дискутира как могат да се приложат на практика техно­логиите, разгледани в предходните теми. Поставена е задача да се раз­работи един сериозен практически проект – система за запознанства в Интернет с възможност за уеб и GUI достъп.

При реализа­цията на системата се преминава през всичките фази от раз­работката на софтуерни проекти: анализиране и дефиниране на изисква­нията, изготвяне на системна архитектура, проектиране на база от данни, имплементация, тестване и внедряване на системата.

При изготвяне на архитектурата приложението се разделя на три слоя – база от данни (която се реализира с MS SQL Server 2000), бизнес слой (който се реализира като ASP.NET уеб услуга) и клиентски слой (който се реализира от две приложения – ASP.NET уеб клиент и Windows Forms GUI клиент).

Ръководител на проекта е Ивайло Христов. Автори на проекта са: Ивайло Христов (отговорен за Windows Forms клиента), Тодор Колев и Ивайло Димов (отговорни за уеб услугата и базата данни) и Бранимир Ангелов (отговорен за ASP.NET уеб клиента). Инсталаторът на проекта е създаден от Галин Илиев. Технически редактори на кода са Мартин Кулов, Светлин Наков, Стефан Добрев и Деян Варчев.

Автори на текста са Ивайло Христов, Тодор Колев, Ивайло Димов и Бранимир Ангелов. Редактор на текста е Светлин Наков.

За използваната терминология

Тъй като настоящият текст е на български език, ще се опитаме да ограни­чим употребата на английски термини, доколкото е възможно. Съществу­ват обаче три основателни причини да използваме и англий­ските тер­мини наред с българските им еквиваленти:

-     По-голямата част от техническата документация за .NET Framework е на английски език (повечето книги и в частност MSDN Library) и затова е много важно читателите да знаят английския еквивалент на всеки използван термин.

-     Много от използваните термини не са пряко свързани с .NET и са навлезли отдавна в програмисткия жаргон от английски език (напри­мер "дебъгвам", "компилирам" и "плъгин"). Тези термини ще бъдат изписвани най-често на кирилица.

-     Някои термини (например "framework" и "deployment") са трудно преводими и трябва да се използват заедно с оригинала в скобки. В настоящата книга на места такива термини са превеждани по раз­лични начини (според контекста), но винаги при първо срещане се дава и оригинални­ят термин на английски език.

Конвенция за кода

С цел уеднаквяване на стила на кода във всички примери от книгата, в примерите и демонстрациите от лекциите, както и в прак­тическия проект, е въведена конвенция за кода, която включва редица препоръки за фор­матирането на кода, имената на типове, членове и променливи, елементи от потребителския интерфейс и други. Ще обясним по-важните от тях:

Константите пишем с главни букви

Примери:

private const int MAX_VALUE = 4096;

private const string INPUT_FILE_NAME = "input.xml";

Това е утвърдена практика, възприета от повечето програмисти на C, C++, Java и C#.

Член-променливите пишем с префикс "m"

Примери:

private Hashtable mUsersProfiles;

private ArrayList mUsers;

Тази конвенция не е стандартна, но тъй като Microsoft нямат официална препоръка по този въпрос, ние възприехме тази конвенция за имену­ване на член-променливите, за да ги отличаваме от останалите промен­ливи. Префиксът "m" произхожда от думата "member" (член).

Параметрите на методите пишем с префикс "a"

Пример:

public void IsLoginValid(string aUserName, string aPassword)

{

  // ...

}

Тази конвенция също не е стандартна, но ние я възприехме, за да можем лесно да отличаваме параметрите в методите от останалите променливи, което често пъти е много полезно. Префиксът "a" произхожда от думата "argument" (аргумент на метод).

Именуване на идентификатори

Възприели сме конвенция за именуване на идентификаторите, която е близка до официалните препоръки на Microsoft (за случаите, в които Microsoft са дали препоръки) и е съобразена с принципите за именуване на член-променливи и параметри, които вече разгледахме. Ето как изг­лежда тази конвенция:

Идентификатор

Стил

Пример

пространство от имена (namespace)

Pascal Case

System.Windows.Forms

тип (клас, структура, ...)

Pascal Case

TextWriter

интерфейс (interface)

Pascal Case, префикс "I"

ISerializable

изброен тип (enum type)

Pascal Case

FormBorderStyle

изброена стойност (enum value)

Pascal Case

FixedSingle

поле само за четене (read-only field)

Pascal Case

UserIcons

поле-константа (constant)

UPPERCASE

MAX_VALUE

свойство (property)

Pascal Case

BorderColor

събитие (event)

Pascal Case

SizeChanged

метод (method)

Pascal Case

ToString()

член-променлива (field)

Pascal Case, префикс "m"

mUserProfiles

статична член-променлива (static field)

Pascal Case, префикс "m"

mTotalUsersCount

параметър на метод (parameter)

Pascal Case, префикс "a"

aFileName

локална променлива (local variable)

Camel Case

currentIndex

Именуване на контроли

При именуване на контроли използваме Pascal Case и представка, която съответства на техния тип. Не слагаме префикс "m", когато контролата е член-променлива:

Контрола

Пример

Button

ButtonOk, ButtonCancel

Label

LabelCustomerName

TextBox

TextBoxCustomerName

Panel

PanelCustomerInfo

Image

ImageProduct

Конвенции за базата данни

Използваме множествено число за именуване на таблици (например Users, Countries, StudentsCourses, ). При имената на колоните в таб­лица използваме Pascal Case (например UserName, MessageSender, UserId и т.н.).

Служебните думи в езика SQL (например SELECT, CREATE TABLE, FROM, INTO, ORDER BY и др.) изписваме с главни букви.

Как възникна тази книга?

Историята на тази книга е дълга и интересна.

Няколко години след официалното излизане на .NET платформата, през 2002 г. .NET Framework вече беше навлязъл широко на пазара и много български фирми разработваха .NET приложения. Езикът C# и .NET плат­формата вече бяха добре познати сред софтуерните специалисти, но по университетите все още никой не преподаваше тези технологии.

В този момент в Софийски университет възникна курсът "Програмиране за платформа .NET".

Курсът по програмиране за платформа .NET в СУ (2002/2003 г.)

Курсът "Програмиране за платформа .NET" в Софийски университет беше организиран през летния семестър на учебната 2002/2003 г. от група студенти с изявен интерес към .NET технологиите, някои от които имаха вече натрупан сери­озен практически опит като .NET разработчици.

Преподавателският екип беше в състав Светлин Наков (работещ тогава в Мусала Софт), Стоян Йорданов (работещ тогава в Рила Солюшънс), Георги Иванов (работещ тогава във WebMessenger) и Николай Недялков (работещ тогава в Информационно обслужване).

Курсът (http://www.nakov.com/dotnet/2003/) обхващаше всички основни технологии, свързани с .NET Framework. Интересът към него беше много голям. Над 300 студента преминаха обучението, което беше с обем 60 учебни часа. Много от тях след това започнаха професионалната си кари­ера като .NET програмисти.

По време на семестъра бяха разработени авторски учебни материали за повечето от темите, които по-късно бяха използвани при изготвянето на лекции по "Програмиране за .NET Framework", на които е базирана насто­ящата книга.

Проектът на Microsoft Research и БАРС

Две години по-късно Microsoft Research отправиха предложение към Софийски университет за участие в академичен проект за създаване на учебно съдържание и учебни материали по дисциплини, изучаването на които е базирано на технологиите на Microsoft.

Екипът на Светлин Наков, съвместно с Българска асоциация на разра­ботчиците на софтуер и Софийски университет предложиха проект за раз­ра­ботка на изчерпателно учебно съдържание и провеждане на универси­тетски курсове по "Програмиране за .NET Framework". Проектът беше одо­брен и частично финансиран от Microsoft Research.

Така започна съставянето на учебните материали, върху които е бази­рана настоящата книга. За година и половина бяха изработени повече от 2000 PowerPoint слайда по 26 теми, съдържащи над 600 примера, около 200 демон­стра­ции на живо и над 300 задачи за упражнения. Учебните материали са с много високо качество и предоставят задълбочена инфор­мация по всички по-важни технологии, свързани с програмирането с .NET Framework. По някои от темите лекциите се получиха значително по-добри от официалните учебни материали на Microsoft (т. нар. Microsoft Official Curriculum). Лекциите са достъпни за свободно изтегляне от сайта на книгата.

Курсът по програмиране за .NET Framework в СУ (2004/2005 г.)

По разработените вече учебни материали през зимния семестър на 2004/2005 г. беше прове­ден курс във Факултета по математика и инфор­матика на Софийски уни­вер­ситет с продължителност 90 учебни часа.

Курсът (http://www.nakov.com/dotnet/) беше организиран от Светлин Наков и неговия екип – Бранимир Гюров, Мартин Кулов, Георги Иванов, Михаил Стойнов и Ивайло Христов. Интересът към курса отново беше голям и стотици студенти избраха да преминат обучението. Мнозина от тях след това започнаха работа като .NET програ­мисти във водещи бъл­гарски софтуерни компании.

Няколко месеца след приключване на курса започна писането и на насто­ящата книга по материалите, използвани в лекциите.

Курсът по програмиране за .NET Framework в СУ (2005/2006 г.)

През зимния семестър на 2005/2006 г. във Факултета по математика и информатика на Софийски университет "Св. Климент Охридски" отново се организира курс по .NET Framework (http://www.devbg.org/dotnetcourse/) с продължителност 90 учебни часа.

Преподавателският екип е съставен от представители на авторския колектив, разработил настоящата книга: Светлин Наков, Ивайло Христов, Михаил Стойнов, Галин Илиев, Васил Бакалов, Стефан Захариев, Радослав Иванов, Антон Андреев, Стефан Кирязов и Виктор Живков.

Курсът се провежда по официалните лекции и учебни материали, разра­ботени по съвместния проект между Microsoft Research, Софийски универ­ситет и БАРС, които са достъпни за свободно изтегляне от сайта на курса.

Настоящата книга се използва като официален учебник в курса.

Проектът за настоящата книга

Първоначално идеята беше да се разпишат като текст изготвените вече лекции и да се компилира учебник за курсовете по програмиране за .NET Framework. По-късно проектът силно се разрасна и в него се включиха над 30 души. Появиха се допълнителни теми, появиха се и множество допълнения към обхванатите в лекциите теми.

Книгата е безплатна!

Настоящата книга се разпространява напълно безплатно в елек­тронен вид по лиценз, който позволява използването й за всякакви цели, включител­но и в комерсиални проекти. Книгата се разпространява и в хартиен вид срещу заплащане, което покрива разходите по отпечатването и разпрост­ранението й, без да се реализира печалба.

Екипът, реализирал идеята

Екипът, написал настоящата книга, е съставен от хора, които имат силен интерес към .NET технологиите и желаят безвъзмездно да споделят своя опит като участват в написването на една или няколко от темите. Някои от участниците в екипа са бивши студенти, посещавали курсовете по .NET Framework в Софийски университет, други са членове на Софий­ската .NET потребителска група (www.sofiadev.org), а трети – разработ­чици, които от някъде са научили за проекта. Всички автори, съавтори и редактори от екипа по разработката на книгата са програмисти с реален практически опит.

Участниците в проекта дадоха своя труд безвъзмездно, без да получат материални или други облаги, защото съзнаваха липсата на добра книга за .NET Framework на български език и имаха силно желание да помогнат на своите настоящи и бъдещи колеги да навлязат с много по-малко усилия в .NET техно­логиите.

Процесът на работа

Написването на книгата отне около 6 месеца. Екипът беше ръководен от Светлин Наков, който има богат опит с писането на статии, презентации и книги и притежава добри технически познания по .NET Framework. Екипът се събираше на всеки 2 седмици за да дискутира напре­дъка по задачите и проблемите, възникнали по време на работата по проекта.

Работата по всяка тема изискваше нейният автор да предава по 10-15 страници на всеки 2 седмици. Този подход доведе до намаляване на риска от закъснение на работата по темите, и позволи проблемите да бъдат идентифицирани и решавани още при възникването им. В крайна сметка проектът завърши успешно, макар и доста след плани­ра­ните първоначал­но срокове.

По време на работата възникваха проблеми, породени от голямото нато­варване на авторите на работното им място. Някои автори трудно успя­ваха да спазят обещаните срокове (а други дори никога не са ги спаз­вали). По време на поправителната сесия някои студенти имаха сериозни трудности. Въпреки това само един участник, който се включи в проекта, в последствие се отказа. Всички останали написаха успешно своите теми.

За улесняване на съвместната работа бе използвана системата за екипна работа по проекти, предлагана свободно от портала sciforge.org. За цели­те на книгата в SciForge беше регистриран и използван проект "Книга за .NET Framework", който все още е публично достъпен от адрес http://sciforge.org/projects/dotnetbook/. Беше използвана системата за контрол на версиите Subversion, форумът и пощенският списък (mailing list), предлагани от SciForge.

За да се уеднаквят стиловете и форматирането във всички глави, беше разработено специално "ръководство за писателите", което дефинираше строги правила, свързани със стила на изказ, структурирането на текста, форматирането на кода, примерите, таблиците, схемите, картинките и т.н. Бяха разработени конвенции за кода, речник на преводните думи и други полезни стандарти. За всяка глава беше направен шаблон за MS Word 2003, в който авторите трябваше да пишат. Всички тези усилия силно ограничиха различията в стила и форматирането между отделните глави на книгата.

Всяка тема, след написването й, беше редактирана и редактирана от поне един редактор. Първоначално всички редакции и рецензии се извършваха от ръководителя на проекта Светлин Наков, но по-късно към редактира­нето се присъединиха и други участници. В резултат на общите усилия съдържа­нието на всички теми е на добро техническо ниво и добре издър­жано откъм стил.

Авторският колектив

Авторският колектив се състои от над 30 души – автори, съавтори, редак­тори и други. Ще представим всеки от тях с по няколко изречения (под­редбата е по азбучен ред).

Александър Русев

Александър Русев е програмист във фирма JCI (www.jci.com), където се занимава с разработка на софтуер за леки автомобили. Завър­шил е Тех­нически университет – София, специалност компютърни системи и техно­логии. Александър се е занимавал и с разработка на софтуер за мобилни теле­фони. Професионалните му интереси включват Java технологиите и .NET платформата. Можете да се свържете с Александър по e-mail: arussev@gmail.com.

Александър Хаджикръстев

Александър Хаджикръстев е софтуерен архитект със сериозен опит в областта на проектирането и разработката на уеб базирани системи и e-commerce приложения. Той е сътрудник и консултант на PC Magazine България (www.sagabg.net/PCMagazine/) и почетен член на Бъл­гарската асоциация на софтуерните разработчици (www.devbg.org). Александър има дългогодишен опит като ръководител на софтуерни проекти във фирми, базирани в България и САЩ. Професионалните му интереси са свързани с проектирането и изграждането на .NET прило­жения, разработ­ването на експертни системи и софтуер за управление и автоматизация на бизнес процеси.

Антон Андреев

Антон Андреев работи като ASP.NET уеб разработчик във фирма TnDSoft (www.tndsoft.com). Той се интересува се от всичко, свързано с компют­рите и най-вече с .NET и Linux. Като ученик се е занимавал с алгоритми и е участвал в олимпиади по информа­тика. Завършил е математическа гим­назия и езикова гимназия с английски език, а в момента е студент в специалност информатика във Факул­тета по матема­тика и информатика (ФМИ) на Софийски университет "Св. Климент Охридски". Работил е и като системен админи­стратор във ФМИ и сега продължава да подпомага проектите на факул­тета, разработвайки нови сайтове. Неговият личен сайт е достъпен от адрес: http://debian.fmi.uni-sofia.bg/~toncho/portfolio/. Можете да се свър­жете с Антон по e-mail: anton.andreev@fmi.uni-sofia.bg.

Бранимир Ангелов

Бранимир Ангелов е софтуерен разработчик във фирма Gugga (www.gugga.net) и студент във Факултета по Математика и информатика на Софийски университет "Св. Климент Охридски", специалност компю­търни науки. Неговите професионални интереси са в областта на обектно-ориен­тирания анализ, моделиране и програмиране, уеб технологиите и в част­ност изграждането на RIA (Rich Internet Applications) и разработката на софтуер за мобилни устройства. Бранимир е печелил грамоти и отли­чия от различни състе­зания, както и първо място на Националната олим­пиада по информаци­онни технологии, на която е бил и жури година по-късно.

Васил Бакалов

Васил Бакалов е студент, последен курс, в Американския университет в България, специалност Информатика. Той е председател на студентския клуб по информационни технологии и е студент-консултант на Microsoft България за университета. В рамките на клуба се занимава с управление на проекти и консултации по изпълнението им. Като студент-консултант на Microsoft България Васил подпомага усилията на Microsoft да поддържа тясна връзка със студентите и да ги информира и обучава по най-новите й продукти и технологии. Васил работи и като сътрудник на PC Magazine България от няколко години и има редица статии и коментари в изда­нието. В университета той предлага и изготвя план за курс по практи­ческо изучаване на роботика, като разширение на обучението по изкуст­вен интелект, който е одобрен и внедрен. Той работи и с няколко ИТ фирми, където изгражда решения, базирани на .NET плат­формата. Прите­жава професио­нална сер­тифика­ция от Microsoft. Можете да се свържете с Васил по e-mail: dotnetbook@vassil.info.

Виктор Живков

Виктор Живков е софтуерен инженер в Интерконсулт България (www.icb.bg). В момента е студент в Софийски Университет "Св. Климент Охридски", специалност информатика. Професионалните му интереси са основно в областта на решенията, базирани на софтуер от Microsoft. Виктор има сериозен опит в работата с .NET Framework, Visual Studio .NET и Microsoft SQL Server. Той участва в проекти за различни информационни системи, главно за Норвегия. Членува в БАРС от 2005 година. За връзка с Виктор можете да използвате неговия e-mail: viktor.zhivkov@gmail.com.

Деян Варчев

Деян Варчев е старши уеб разработчик във фирма Vizibility (www.vizibility.net). Неговите отговорности включват проектиране­то и разработката на уеб базирани приложения, използващи последните тех­нологии на Microsoft, проучване на новопоявяващи се технологии и пла­ниране на тяхното внедряване в производството, както и обучение на нови колеги. Неговите професионални интереси са свързани тясно с технологиите на Microsoft – .NET платформата, SQL Server, IIS, BizTalk и др. Деян е студент по информатика във Факултета по математика и информатика на Софийски университет "Св. Климент Охридски".

Димитър Бонев

Димитър Бонев е софтуерен разработчик във фирма Formula Telecom Solutions (www.fts-soft.com). Той отговаря за разработването на уеб бази­рани приложения за корпоративни клиенти, както и за някои модули и инструменти, свързани с вътрешния процес на разработка във фирмата. Професионалните му интереси са насочени предимно към .NET платфор­мата, методологията extreme programming и софтуерния дизайн. Димитър е завършил ВВВУ "Г. Бенковски", специалност компютърна техника. Той има богат опит в разработването на софтуерни решения, предимно с тех­нологиите на Microsoft и Borland.

Димитър Канев

Димитър Канев е разработчик на софтуер във фирма Медсофт (www.medsoft.biz). Той е завършил Факултета по математика и информа­тика на Софийски университет "Св. Кли­мент Охридски", специалност информатика. Професио­налните му интере­си са основно в областта на решенията, базирани на софтуер от Microsoft. Димитър има сериозен опит в работата с Visual Studio .NET, Microsoft SQL Server и ГИС системи. Рабо­тил е в проекти за изграждане на големи информационни системи, свър­зани с ГИС решения, и експертни системи за медицински лаборатории.

Галин Илиев

Галин Илиев е ръководител на проекти и софтуерен архитект в бъл­гарския офис на Technology Services Consulting Group (www.wordassist.  com). Галин е участвал в проектирането и разработ­ването на големи информационни системи, Интернет сайтове с управление на съдържа­нието, допълнения и интеграция на MS Office със системи за управление на документи. Той притежава степен бакалавър по менидж­мънт и инфор­ма­ционни технологии, а също и сертификация MCSD за Visual Studio 6.0 и Visual Studio .NET. Той има сериозен опит с работата с Visual Studio .NET, MS SQL Server, MS IIS и MS Exchange. Личният му сайт е достъпен от адрес www.galcho.com, а e-mail адресът му е Iliev@galcho.com.

Георги Пенчев

Георги Пенчев е софтуерен разработчик във фирма Symex България (www.symex.bg), където отговаря за разработка на финансово ориенти­рани графични Java приложения и на Интернет финансови портали с Java и PHP. Участвал е в изграждането на продукти за следене и обработка на борсови индекси и котировки за Българската фондова борса. Георги е студент по информатика във Факултета по математика и инфор­матика на Софийски университет "Св. Климент Охридски". Професионалните и ака­де­мичните му инте­реси са насочени към Java и .NET технологиите, биоин­форматикатa, тео­ретичната информатика, изкуствения интелект и базите от знания. През 2004 и 2005 г. е асистент в курса по "Информационни технологии" за студенти с нарушено зрение и в практическия курс по "Структури от данни и програ­миране" в Софийски университет. Можете да се свържете с Георги по e-mail: pench_wot@yahoo.com.

Иван Митев

Иван Митев е софтуерен разработчик във фирма EON Technologies (www.eontechnologies.bg). Той е завършил Факултета по математика и информатика на Софийски университет "Св. Климент Охридски", специал­ност информатика. Иван е участвал в проектирането и реализацията на множество информа­ционни системи, основно ГИС решения. Професионал­ният му опит е в разработки предимно с продукти и технологии на Microsoft. Основните интереси на Иван са в създаването на качествени и ефективни софтуерни решения чрез използването на подходящи прак­тики, технологии и инстру­менти. Технически уеблог, който той поддържа от началото на 2004 година, е с акцент върху .NET програмирането и е достъпен на адрес http://immitev.blogspot.com. Можете да се свържете с Иван по e-mail: immitev@gmail.com.

Ивайло Димов

Ивайло Димов е софтуерен разработчик във фирма Gugga (www.gugga.com). Неговите интереси са в областта на обектно-ориенти­раното моделиране, програмиране и анализ, базите от данни, уеб прило­женията и приложения, базирани на Microsoft .NET Framework. В момента Ивайло е студент във Факултета по математика и информатика на Софий­ски университет "Св. Климент Охридски", специалност Компютърни науки. Той е сертифициран от Microsoft разработчик и е печелил редица грамоти и отличия от състе­зания по програмиране. През 2004 г. е победител в Националната олим­пиада по информационни технологии и е участвал в журито на същата олимпиада година по-късно.

Ивайло Христов

Ивайло Христов е преподавател в Софийски университет "Св. Климент Охридски", където води курсове по "Програмиране за .NET Framework", "Качествен програмен код", "Увод в програмирането", "Обектно-ориенти­рано програмиране" и "Структури от данни в програмирането". Неговите професионални инте­реси са в областта на .NЕТ технологиите и Интернет технологиите. Като ученик Ивайло е участник в редица национални състе­зания и конкурси по програмиране и е носител на престижни награди и отличия. Той участва в екип, реализирал образователен проект на Microsoft Research в областта на .NET Framework. Личният сайт на Ивайло е достъпен от адрес: www.ivaylo-hristov.net.

Лазар Кирчев

Лазар Кирчев е завършил Факултета по математика и информатика на Софийски университет "Св. Климент Охридски" и в момента е дипломант в специализация "Информационни системи". Той работи в Института за паралелна обра­ботка на информацията към БАН по съвместен проект между Факултета по математика и информатика и БАН за изграждане на grid система. Неговите интереси включват .NET платформата, grid систе­мите и базите от данни.

Манол Донев

Манол Донев е софтуерен разработчик във фирма telerik (www.telerik.  com). Той е част от екипа, който разработва уеб-базираната система за управление на съдържание Sitefinity (www.sitefinity.com). Манол е студент във Факултета по математика и информатика на Софийски университет "Св. Климент Охридски", специалност Информатика. Неговите професио­нални интереси обхващат най-вече .NET технологиите (в частност ASP.NET уеб приложе­ния, XML и уеб услуги). Можете да се свържете с Манол по e-mail: manol.donev@gmail.com.

Мартин Кулов

Мартин Кулов е изпълнителен директор на фирма КодАтест (www.  codeattest.com), в която разработва системи за управление на качеството и автоматизация на софтуерното производство. Той има дългогодишен професионален опит като разработчик и ръководител в раз­лични по голе­мина проекти за частния и обществения сектор. Интере­сите му са в областта на продуктите и технологиите на Microsoft. Мартин е сер­тифи­циран от Microsoft разработчик по програмите MCSD и MCSD.NET (Charter Member). Той е магистър инженер при Факултета по комуника­ционна техника и технологии на Технически университет – София. През 2004 г. той участва като лектор в курсовете "Програмиране за .NET Framework" и "Качествен програмен код" в Софийски университет "Св. Климент Охрид­ски". Мартин е лектор и на семинари на Microsoft, свър­зани с .NET техно­логиите и разработката на софтуер. Той е почетен член на Българ­ската асоциация на разработчиците на софтуер и член на SofiaDev .NET потребителската група. Можете да се свържете с него по e-mail: martin@codeattest.com или чрез неговия личен уеблог: http://www.  codeattest.com/blogs/martin/.

Михаил Стойнов

Михаил Стойнов е софтуерен разработчик във фирма MPS (www.mps.bg), която е подизпълнител на Siemens A.G. Той се занимава професи­онално с програмиране за платформите Java и .NET Framework от няколко години. Участва като лектор в преподава­телския екип на курсовете "Програмира­не за .NEТ Framework" и "Качес­твен програмен код". Той е студент-кон­султант на Майкро­софт България за Софийски университет през послед­ните 2 години и подпомага раз­пространението на най-новите продукти и технологии на Microsoft в университета. Михаил е бил лектор на меж­дународни конференции за ГИС сис­теми. Интересите му обхващат разра­ботка на уеб приложения, прило­же­ния с бази от данни, изграждане на сървърни системи и участие в ака­де­мични дейности.

Моника Алексиева

Моника Алексиева е софтуерен разработчик във фирма Солвер / Мидакс (www.midax.com). В момента следва специалност информатика във Факул­тета по математика и информатика на Софийски университет "Св. Климент Охридски". Моника има професионален опит в разработката за .NET Framework с езика C# и е сертифициран от Microsoft разработчик за .NET платформата. Нейните интереси са в областта на технологиите за изграж­дането на графичен пот­ребителски интерфейс и разработката на прило­жения за мобилни уст­ройства. През 2004 година Моника е асистент по "Структури от Данни" в Софийски университет.

Николай Недялков

Николай Недялков е президент на Асоциацията за информационна сигур­ност (www.iseca.org) която е създадена с цел прилагане на най-добрите практики за осигуряване на информационната сигурност на национално ниво и при извършването на електронен бизнес. Николай е професиона­лен разработчик на софтуер, консултант и преподавател с дългогодишен опит. Той е автор на статии и лектор на множество конференции и семи­нари в област­та на софтуерните техноло­гии и информационна си­гурност. Преподавателският му опит се простира от асистент по "Струк­тури от данни в програмирането", "Обектно-ориентирано програ­ми­ране със C++" и "Visual C++" до лектор в курсовете "Мрежова сигур­ност", "Сигурен програмен код", "Интернет програмиране с Java", "Кон­струиране на качествен програмен код", "Програмиране за платформа .NET" и "Раз­работка на приложения с Java". Интересите на Николай са концентрирани върху техническата и бизнес страната на информацион­ната сигурност, Java и .NET технологиите и моделирането и управлението на бизнес про­цеси в големи организации. Николай има бакалавърска степен от Факул­тета по математика и информатика на Софийски университет "Св. Климент Охридски". Като ученик е дългогодишен състеза­тел по програмиране, с редица призови отличия. През 2004 г. е награден от Президента на България Георги Първанов за приноса му към развитието на информаци­онните технологии и информационното общество. Той е почетен член на БАРС. Личният му сайт е достъпен от адрес: www.nedyalkov.com.

Панайот Добриков

Панайот Добриков е софтуерен архитект в SAP A.G., Java Server Technology (www.sap.com), Германия и е отговорен за координа­цията на софтуерните разработки в SAP Labs България. Той е завършил Факултета по математика и информатика на Софийски университет "Св. Климент Охридски", специалност информатика. Панайот е дългогодишен участник (като състе­зател и ръководител) в ученически и студентски състезания по програми­ране и е носител на много престижни награди в страната и чужбина. Той е автор на книгите "Програмиране = ++Алгоритми;" (www. algoplus.org) и "Java Programming with SAP Web Application Server", както и на десетки научно-технически публикации. През периода 2001-2003 води курсовете "Проек­ти­ране и анализ на компютърни алгоритми" и "Прагматика на обектното програмиране" в Софийски университет. Може­те да се свържете с Панайот по e-mail: dobrikov@gmail.com.

Преслав Наков

Преслав Наков е аспирант по изкуствен интелект в Калифорнийския университет в Бъркли (www.berkeley.edu), САЩ. Неговият профе­сионален опит включва шестгодишна работа като софтуерен разработчик във фир­мите Комсофт (www.comsoft.bg) и Рила Солюшънс (www.rila.bg). Инте­ре­сите му са в областта на компютърната лингвистика и биоинформа­тикатa. Преслав получава магистърската си степен по информатика от Софийски университет "Св. Климент Охридски". Той е носител е на бронзов медал от Балканиада по инфор­матика, заемал призови места в десетки национални състезания по прог­рамиране като ученик и студент. Състезател е, а по-късно и тре­ньор на отбора на Софийския университет, участник в Светов­ното между­университетско състезание по програмиране (ACM International Collegiate Programming Contest). Той е асистент в мно­жество курсове във Факултета по математика и информатика на Софийски университет, лектор-основател на курсовете "Проектиране и анализ на компютърни алгоритми" и "Моделиране на данни и проектиране на бази от данни". Преслав е автор на книгите "Основи на компютър­ните алгорит­ми" и "Прог­рамиране = ++Алгоритми;" (www.algoplus.org). Той има десетки научни и научнопопулярни публикации в престижни между­народни и национални издания. Той е първият носител на наградата "Джон Атанасов" за принос към развитието на информационните техно­логии и информационното общество, учредена от президента на България Георги Първанов.

Радослав Иванов

Радослав Иванов е софтуерен разработчик във фирма Медсофт (www.  medsoft.biz) и студент в специалност информатика във Факултета по мате­матика и информатика на Софийски университет "Св. Климент Охридски". Професио­налните му интереси са в областта на информационната сигур­ност и про­дуктите и технологиите на Microsoft.

Светлин Наков

Светлин Наков е директор на Националната академия по разработка на софтуер (http://academy.devbg.org), където обучава софтуерни специа­листи за практическа работа в ИТ индустрията. Той е хоноруван пре­подавател по съвременни софтуерни технологии в Софийски университет "Св. Климент Охридски", където води курсове по "Проектиране и анализ на компютърни алгоритми", "Интернет програмиране с Java", "Мрежова сигурност", "Програмиране за .NET Framework" и "Качествен програмен код". Светлин има сериозен професио­нален опит като софтуерен разра­ботчик и консултант. Неговите интереси обхващат Java технологиите, .NET платформата и информационната сигурност. Той е завършил бакалавър­ската и магистърската си степен във Факултета по математика и информа­тика на Софийски университет "Св. Климент Охридски". Като ученик и студент Светлин е победител в десетки национални състе­зания по програ­миране и е носител на 4 медала от международни олимпи­ади по информа­тика. Той има десетки научни и технически публикации, свързани с раз­работката на софтуер, в български и чуждестранни списа­ния и е автор на книгите "Интернет програмиране с Java" и "Java за цифрово подпис­ване на документи в уеб". През 2003 г. той е носител на наградата "Джон Атанасов" на фондация Еврика. През 2004 г. получава награда "Джон Атанасов" от президента на България Георги Първанов за приноса му към развитието на информационните технологии и информа­ционното общест­во. Светлин е един от учредителите на Българската асо­циация на разра­ботчиците на софтуер (www.devbg.org) и понастоящем неин председател.

Стефан Добрев

Стефан Добрев е старши уеб разработчик във фирма Vizibility (www.vizibility.net). Той отговаря за голяма част от .NET продук­тите, раз­работвани в софтуерната компания, в това число уеб базирана система за изграждане на динамични сайтове и управление на тяхното съдържание, уеб система за управление на контакти и др. Негова отго­ворност е и внедряването на утвърдените практики и методологии за раз­работка на софтуер в производствения процес. Професионалните му интереси са насочени към уеб технологиите, в частност ASP.NET, XML уеб услугите и цялостната разработка на приложения, базирани на .NET Framework. Стефан следва информа­тика във Факултета по математика и информатика на Софийски университет "Св. Климент Охридски".

Стефан Кирязов

Стефан Кирязов е софтуерен разработчик във фирма Verix (www.verix.bg). Той се занимава професионално с разработка на .NET решения за бизнеса и държавната администрация. Опитът му включва изграждане на уеб и настолни приложения с технологии на Microsoft, а също и Java и Oracle. Завършил е Факултета по математика и информатика на Софийски университет "Св. Климент Охридски", специалност информатика. Неговите професионални интереси включват архитектура, дизайн и методологии за разработка на големи корпоративни приложения. За контакти със Стефан можете да използвате неговия e-mail: skiryazov@verix.bg.

Стефан Захариев

Стефан Захариев работи като софтуерен разработчик в Интерконсулт България (www.icb.bg), където е отговорен за създаването на инструменти за автоматизиране на процеса на разработка. Той има дълго­годишен опит в създаването на ERP системи, който натрупва при работата си в различни фирми в България. Основните му интереси са свързани със системите за управление на бази от данни, платформата .NET, ORM инструментите, J2ME, както и Borland Delphi. При завършването си на средното образова­ние в "Технологично училище – Електронни системи", печели отличителна награда за цялостни постижения. През 2005 г. завър­шва "Технически университет – София", където се дипломира като бака­лавър във факулте­та по "Компютърни системи и управление". Той членува в БАРС и в Софийската .NET потребителска група Можете да се свържете със Стефан по e-mail: stephan.zahariev@gmail.com.

Стоян Дамов

Стоян Дамов е софтуерен консултант, пич, поет и революционер. Можете да се свържете с него по e-mail: stoyan.damov@gmail.com или от неговия личен сайт: http://spaces.msn.com/members/stoyan/.

Тодор Колев

Тодор Колев е софтуерен разработчик в Gugga (www.gugga.com) и сту­дент във Факултета по математика и информатика на Софийски универ­ситет "Св. Климент Охридски", специалност Информатика. Неговите про­фесио­нални интереси са в областта на обектно-ориентирания анализ, моделиране и програми­ране, уеб технологиите, базите данни и RIA (Rich Internet Applications). Тодор е дългогодишен участник в състезания по информатика и информа­ционни технологии, печелил редица грамоти и отличия, както и сребърен медал на международна олимпиада по инфор­мационни технологии. Той е носител на първо място от националната олимпиада по информационни технологии и е участвал в журито на същата олимпиада година по-късно. Тодор има множество разработки в сферата на уеб технологиите и е участвал в изследователски екип в Масачузетският технологичен инсти­тут (MIT). Той е сертифициран Microsoft специалист.

Христо Дешев

Христо Дешев е разработчик на ASP.NET компоненти във фирма telerik (www.telerik.com). Той е завършил Американския университет в България, специалност информатика. Основните му интереси са в областта на подо­бряването на процеса на разработка на софтуер. Той е запален привър­женик на Agile методологиите, основно на Extreme Programming (XP). Про­фесионалният му опит е предимно в разработката на решения с кратък цикъл за обратна връзка, високо покритие от тестове и почти пълна автоматизация на всички нива от работния процес.

Христо Радков

Христо Радков е управител на фирма за софтуерни консултантски услуги Calisto ID (www.calistoid.com). Той е бакалавър от английската специал­ност "Manufacturing Engineering" в Технически Университет – София и магистър по информаци­онни и комуникационни технологии във Факултета по математика и информатика на Софийски университет "Св. Климент Охридски". Христо има дългогодишен опит с различни сървъри за бази от данни и сериозен опит с различни технологии на Microsoft, Borland, Sun и Oracle. Участник и ръководител е в проекти за изграждане на няколко големи и няколко по-малки информа­ционни системи, динамични Интернет сайтове и др. Под негово ръковод­ство е създаден най-успешния складово-счетоводен соф­туер за фарма­цевтични предприятия в страната. Като ученик Христо има множество участия и награди от олимпиади по мате­матика в страната и чужбина.

Цветелин Андреев

Цветелин Андреев е софтуерен разработчик във фирма Komero Technologies (www.komero.net). Той отговаря основно за UNIX базираните решения и за модули, свързани с вътрешния процес на разработка. В момента Цветелин е студент във Факултета по математика и информатика на Софийски университет "Св. Климент Охридски" и е професионално серти­фициран от Sun. Неговите интереси са основно в областта на Java и UNIX технологиите, но обхващат и области от .NET платформата, изкуст­вен интелект, мрежова сигурност, анализ на изисквания, софтуерни архитектури и дизайн. Личният сайт на Цветелин е достъпен от адрес: www.flowerlin.net.

Явор Ташев

Явор Ташев е софтуерен разработчик във фирма TND Soft (www.tndsoft.com). Той е завършил Факултета по математика и информа­тика на Софийски университет "Св. Климент Охридски", специалност информатика. Участвал е в разработката на големи корпоративни сайтове и комуника­ционни системи, базирани на технологиите и платформите на Microsoft. Интере­сите му са насо­чени към .NET платформата, Java и из­куствения интелект. Професионал­ният му опит е свързан предимно с .NET Framework, Visual Studio .NET, Microsoft SQL Server и Microsoft Internet Information Server.

Благодарности

Настоящата книга стана реалност благодарение на много хора и няколко организации, които помогнаха и допринесоха за проекта. Нека изкажем своята благодарност и уважение към тях.

Светлин Наков

На първо място трябва да благодарим на главния орга­низатор и ръково­дител на проекта, Светлин Наков, който успя да мотивира над 30 души да участват в начи­нанието и успя да ги ръководи успешно през всичките месеци на работата по проекта. Той успя да реализира своята идея за създаване на чисто българска книга за програмиране с .NET Framework най-вече благодарение на всички доб­роволни участници, които дариха своя труд за проекта и отделиха от малкото си свободно време за да спо­делят своите знания и опит безвъзмездно, за каузата.

Авторският колектив

Авторският колектив е наистина главният виновник за съществуването на тази книга. Текст с такъв обем и такова качество не може да бъде написан от един или двама автора за по-малко от няколко години, а до тогава инфор­мацията може вече да остаряла.

Идеята за участие на толкова много автори се оказа успешна, макар и координацията между тях да не беше лесна. Въпреки, че отделните глави от книгата са писани от различни автори, те следват единен стил и високо качество. Всички глави са добре структурирани, с много заглавия и подза­главия, с много и подходящи примери, с добър стил на изказ и еднакво форматиране.

Българска асоциация на разработчиците на софтуер

Проектът получи силна подкрепа от Българската асоциация на разработ­чиците на софтуер (БАРС), тъй като е в синхрон с нейните цели и идеи.

БАРС официално държи правата за издаване и разпространение на кни­гата в хартиен вид, но няма право да реализира печалба от тази дей­ност. Асоциацията чрез своите контакти успя да намери финансиране за отпе­чатването на книгата, както и хостинг за нейния уеб сайт и форум.

Microsoft Research

В ранните си фази, когато бяха изготвени лекциите за курса "Програ­миране за .NET Framework", проектът получи подкрепа и частично финан­сиране от Microsoft Research. Ако не беше тази подкрепа, вероятно няма­ше да се стигне до създаването на лекциите и до написването на книгата.

SciForge.org

Порталът за организиране на работата в екип SciForge.org даде своя при­нос към проекта, като предостави среда за съвместна работа, включваща система за контрол над версиите, форум, пощенски списък (mailing list) и някои други средства за улеснение на работата.

Благодарностите са отправени главно към създателя на портала и негов главен администратор Калин Наков (www.kalinnakov.com), който указваше редовно съдействие в случай на технически проблеми.

Софийски университет "Св. Климент Охридски"

Факултетът по математика и информатика (ФМИ) на Софийски универ­ситет "Св. Климент Охридски" подпомогна проекта глав­но в началната му фаза, като подкрепи предложението на преподавателския екип от курса "Програми­ране за платформа .NET" за участие в конкурса на Microsoft Research.

Благодарностите са отправени към ст. ас. Елиза Стефанова (която оформи изключително убедително текста на предложението за проекта към Microsoft Research) и доц. Магда­лина Тодорова (която пое ролята на адми­нистра­тивен ръководител при взаимо­отношенията с Microsoft).

По-късно, когато проектът на MS Research приключи и започна работата по настоящата книга, ФМИ предостави зали и техника за провеждане на регулярните срещи на авторския колектив.

telerik

Софтуерната компания telerik (www.telerik.com) подкрепи проекта чрез осигуряване на финансиране за отпечатване на книгата на хартия. Изказ­ваме благодарности от името на целия авторски колектив.

Други

Изказваме благодарности още към:

-     Георги Иванов, ръководител на проекти във фирма Sciant (www.sciant.com), участник в преподавателския екип на курсовете по "Програмиране за .NET Framework". Участник в създаването на лекциите, по които е изградена настоящата книга.

-     Стоян Йорданов, софтуерен инженер в Microsoft Corporation, Redmond (www.microsoft.com), участник в преподавателския екип на курсовете по "Програмиране за .NET Framework". Участник в създа­ването на лекциите, по които е изградена настоящата книга.

-     Бранимир Гюров, частичен съавтор на една от главите на книгата, участник в преподавателския екип на курса "Програмиране за .NET Framework". Участник в създава­нето на лекциите, на които се осно­вава настоящата книга.

-     Невена Партинова, графичен дизайнер. Благодарности за изготвя­нето на корицата на книгата и за цялото търпение по време на продължи­телните дискусии за графичния дизайн и цветовата гама.

-     Михаил Балабанов, преводач и автор на спецификации за превод на софтуер, участник в превода на OpenOffice.org. Благодарности за помощта при превода на някои технически термини.

-     Никола Касев, взел участие при създава­нето на лекциите, по които е изгра­дена настоящата книга.

-     Свилена Момова, частичен съавтор на една от главите на книгата.

-     Веселин Райчев, частичен съавтор на една от главите на книгата.

Сайтът на книгата

Официалният уеб сайт на книгата "Програмиране за .NET Framework" е достъпен от адрес: http://www.devbg.org/dotnetbook/. От него можете да изтеглите цялата книга в електронен вид, лекциите, на които тя е бази­рана, както и сорс кода на практическия проект от глава 29, за който има специално изготвена инсталираща програма.

Към книгата е създаден и дискусионен форум, който се намира на адрес: http://www.devbg.org/forum/index.php?showforum=30. В него можете да дискутирате всякакви технически и други проблеми, свързани с книгата, да отправяте мнения и коментари и да задавате въпроси към авторите.

Лиценз

Книгата и учебните материали към нея се разпространяват свободно по следния лиценз:

Общи дефиниции

1.  Настоящият лиценз дефинира условията за използване и разпрост­ранение на комплект учебни материали и книга по "Програмиране за .NET Framework", разработени от екип под ръководството на Светлин Наков (www.nakov.com) с подкрепата на Българска асоциа­ция на разработ­чиците на софтуер (www.devbg.org) и Microsoft Research (research.microsoft.com).

2.  Учебните материали се състоят от:

-     презентации;

-     примерен сорс код;

-     демонстрационни програми;

-     задачи за упражнения;

-     книга (учебник) по програмиране за .NET Framework с езика C#.

3.  Учебните материали са достъпни за свободно изтегляне при усло­вията на настоящия лиценз от официалния сайт на проекта:

http://www.devbg.org/dotnetbook/

4.  Автори на учебните материали са лицата, взели участие в тяхното изработване. Всеки автор притежава права само над продуктите на своя труд.

5.  Потребител на учебните материали е всеки, който по някакъв начин използва тези материали или части от тях.

Права и ограничения на потребителите

1.  Потребителите имат право:

-     да използват учебните материали или части от тях за всякакви цели, включително да ги да променят според своите нужди и да ги използват при извършване на комерсиална дейност;

-     да използват сорс кода от примерите и демонстрациите, включени към учебните материали или техни модификации, за всякакви нужди, включително и в комерсиални софтуерни продукти;

-     да разпространяват безплатно непроменени копия на учебните материали в електронен или хартиен вид;

-     да разпространяват безплатно оригинални или променени части от учебните материали, но само при изричното споменаване на източника и авторите на съответния текст, програмен код или друг материал.

2.  Потребителите нямат право:

-     да разпространяват срещу заплащане учебните материали или части от тях (включително модифицирани версии), като изклю­чение прави само програмният код;

-     да премахват настоящия лиценз от учебните материали.

Права и ограничения на авторите

1.  Всеки автор притежава неизключителни права върху продуктите на своя труд, с които взима участие в изработката на учебните мате­риали.

2.  Авторите имат право да използват частите, изработени от тях, за всякакви цели, включително да ги изменят и разпространяват срещу заплащане.

3.  Правата върху учебните материали, изработени в съавторство, са притежание на всички съавтори заедно.

4.  Авторите нямат право да разпространяват срещу заплащане учебни материали или части от тях, изработени в съавторство, без изрич­ното съгласие на всички съавтори.

Права и ограничения на БАРС

Ръководството на Българска асоциация на разработчиците на софтуер (БАРС) има право да разпространява учебните материали или части от тях (включително модифицирани) безплатно или срещу заплащане, но без да реализира печалба от продажби.

Права и ограничения на Microsoft Research

Microsoft Research има право да разпространява учебните материали или части от тях по всякакъв начин – безплатно или срещу заплащане, но без да реализира печалба от продажби.

 

Светлин Наков,

24.09.2005 г.


Национална академия по разработка на софтуер

Лекторите

» Светлин Наков е автор на десетки технически публи­ка­ции и ня­колко книги, свър­­зани с раз­работката на соф­ту­ер, заради което е тър­сен лектор и кон­султант.

Той е разработчик с дъл­гого­дишен опит, работил по раз­нообразни проекти, реали­зи­рани с раз­лични техноло­гии (.NET, Java, Oracle, PKI и др.) и преподавател по съвре­мен­ни софтуерни технологии в СУ "Св. Климент Охридски".

През 2004 г. е носител на награ­дата "Джон Атанасов" на прези­дента на България Ге­орги Пър­ва­нов.

Светлин Наков ръководи обу­чението по Java технологии в Академията.

 

» Мартин Кулов е софтуерен инженер и консул­тант с дългогодишен опит в изграждането на решения с платформите на Microsoft.

Мартин е опитен инструктор и сертифициран от Майкрософт разработчик по програмите MCSD, MCSD.NET, MCPD и MVP и меж­дународен лектор в световна­та организа­ция на .NET потре­бителски­те групи INETA.

Мартин Кулов ръководи обу­чението по .NET технологии в Академията.

Академията

» Национална академия по раз­ра­ботка на софтуер (НАРС) е център за професионално обу­чение на соф­ту­ерни специалисти.

 

» НАРС провежда БЕЗПЛАТНО кур­сове по разработка на софтуер и съв­ременни софтуерни тех­нологии в Со­фия и други градове.

 

» Предлагани специалности:

§  Въведение в програмирането (с езиците C# и Java)

§  Core .NET Developer

§  Core Java Developer

 

» Качествено обу­чение с много практически про­екти и индивиду­ално внимание за всеки.

 

» Гарантирана работа! Трудов до­говор при постъпване в Академията.

 

» БЕЗПЛАТНО!

Учите безплатно във въведителните курсове и по стипендии от работода­телите в следващите нива.

http://academy.devbg.org


Глава 1. Архитектура на платформата .NET и .NET Framework

Необходими знания

-     Познания по програмиране

-     Езици за програмиране

-     Среди за разработка на софтуер

Съдържание

-     Какво е .NET?

-     Архитектура на платформата Microsoft .NET

-     Какво е .NET Framework?

-     Архитектура на .NET Framework

-     Common Language Runtime (CLR)

-     Управляван код

-     Междинен език IL

-     Модел за изпълнение на IL кода

-     Асемблита и метаданни

-     .NET приложения

-     Домейни на приложението

-     Common Language Specification (CLS), Common Type System (CTS)

-     Common Language Infrastructure (CLI) и интеграцията на различни езици

-     Framework Class Library

-     Интегрирана среда за разработка Visual Studio .NET

В тази тема ...

В настоящата тема ще представим платформата .NET, която въплъщава визията на Microsoft за развитието на информаци­онните и соф­туерните техноло­гии, след което ще разгледаме средата за разработка и изпълне­ние на .NET приложения Microsoft .NET Framework. Ще обърнем внимание на управлявания код, на езика IL, на общата среда за контроли­рано изпълнение на управляван код (Common Lnaguage Runtime) и на модела на компилация и изпълнение на .NET кода. Ще разгледаме още Common Language Specification (CLS), Common Type System (CTS), Common Language Infrastructure (CLI), интеграцията на различни езици, библиоте­ката от класове Framework Class Library и интегрираната среда за разра­ботка Visual Studio .NET.


Какво представлява платформата .NET?

Microsoft дефинират платформата .NET като съвкупност от технологии, които свързват хората с информацията – навсякъде, по всяко време, от всяко устройство. Това определение звучи като маркетингова пропаганда, но .NET е не само технология, тя е и идеология. Платформата въплъщава визията на Microsoft, че информа­ци­ята трябва да бъде максимално дос­тъпна за хората.

.NET платформата осигурява стандартизирана инфраструктура за разра­ботка, използване, хостинг и интеграция на .NET приложения и XML уеб услуги, базирана на .NET сървърите на Microsoft, средствата за разработка (.NET Framework и Visual Studio .NET), идеологията на smart клиентите и т. нар. .NET Building Block Services.

Визията на Microsoft

Визията на Microsoft за .NET е да създадат платформа, която да може да обеди­нява хетеро­генна инфра­структура от сървъри, да интегрира бизнес проце­сите на различни компа­нии по стандартен начин, и да предоставя на потреби­телите достъп до информацията, която им е нужна, по всяко време, от всяко място и от всяко устройство. Както ще видим по-нататък, Microsoft са направили голяма крачка напред към реализирането на тази визия, като са поставили една стабилна технологична основа за разработ­ка и изпълнение на приложения – Microsoft .NET Framework.

Разграничайвате понятията "платформа .NET" и ".NET Framework"!

.NET платформата е визията на Microsoft за развитието на технологиите и осигурява глобална инфраструктура за ре­ализацията на тази визия.

.NET Framework е само част от .NET платформата – тази част, която е насочена към разработчиците на софтуер. Тя осигурява среда за разработка и контролирано изпълне­ние на .NET приложения и предоставя програмен модел и библиотеки от класове за разработка, независима от ези­ците за програмиране.

Имайте предвид, че много често под .NET се подразбира не платформата .NET, а средата .NET Framework, например ".NET език", ".NET приложение" и т. н. В настоящата книга също ще подразбираме под .NET не .NET плат­формата, а .NET Framework.

Архитектура на .NET платформата

Платформата .NET обединява в себе си четири технологични и идео­логически компонента: инфраструктурата от сървъри .NET Enterprise Servers, средствата за разработка .NET Framework и Visual Studio .NET 2003, глобалните услуги .NET Building Block Services и идеологията .NET Smart Clients:

Всеки един от изброените компоненти на .NET платформата е достатъчно обемна тема, за да й се посвети цяла отделна книга, но нашата цел е само да се запознаем накратко с посочените технологии и идеологии, без да навлизаме в подробности. Нека сега ги разгледаме една по една.

.NET Enterprise Servers

.NET Enterprise Servers предоставят сървърната инфраструктура на .NET платформата и съще­временно среда за изпълнение, управление и инте­грация на XML уеб услуги.

Ключови характеристики

Ключовите характеристики на .NET Enterprise сървърите са:

-     Силна поддръжка на XML – всички .NET сървъри използват широко XML стандарта за представяне и обмяна на информация.

-     Висока надеждност – ключова характеристика, изключително важна за бизнеса.

-     Добра скалируемост – възможност за поемане на огромно натовар­ване при необходимост.

-     Оркестрация на бизнес процесите в приложенията и услугите (business process orchestration) – дава се възможност за схематично дефиниране на работните процеси по утвърдени стандарти (като BPEL) и контролираното им изпълнение, наблюдение и управление.

-     Повишена сигурност – сигурността е основна архитектурна концеп­ция при .NET сървърите.

-     Лесно управление – леснота за администриране, настройка, наблю­дение и управление на работата на сървърите.

По-важните сървърни продукти

Microsoft разработват сървърни продукти от много години и в момента предлагат цяло семейство от специализирани сървъри, насочени към различни бизнес нужди. Ще дадем съвсем кратко описание на най-важните от тях:

-     Microsoft Windows Servers Family – представлява фамилия сървърни операционни системи (като Windows 2000 Server и Windows 2003 Server).

-     Microsoft Internet Information Server – представлява уеб сървър, който е част от Windows. Служи за хостинг на уеб сайтове със статично и динамично съдържание.

-     Microsoft SQL Server – служи за управление на релационни бази от данни, многомерни данни и XML.

-     Microsoft BizTalk Server – използва се за интеграция и оркестрация на бизнес процеси, услуги и системи.

-     Microsoft Exchange – позволява координация на съвместната работа в организации. В частност осигурява поддръжката на пощенски услуги (e-mail).

-     Microsoft SharePoint Portal Server – позволява сътрудничество и споделяне на информация в реално време. Улеснява конкурентната работа с общи документи и работата в екип.

-     Microsoft Host Integration Server – позволява интеграция на стари системи.

-     Microsoft Application Center – осигурява хостинг, управление и мониторинг на критични за бизнеса приложения.

-     Microsoft Content Management Server – служи за изграждане, поддръжка и управление на уеб съдържание.

-     Microsoft Mobile Information Server – позволява интеграция с мобилни приложения.

-     Microsoft Internet Security and Acceleration Server – контрол и защита на връзката с Интернет. Предоставя защитна стена (firewall) с възможност за филтриране и анализ на трафика на различни нива.

-     Microsoft Commerce Server – използва се за реализация на приложения за електронна търговия.

.NET Framework и Visual Studio .NET 2003

.NET Framework е софтуерна платформа за разработка и изпълнение на .NET приложения. Тя представлява предоставя програмен модел и стан­дартна библиотека с класове за разработка на приложения и унифи­ци­рана среда за изпълнение на управляван код. Поддържа различни езици за програмиране и позволява тяхната съвместна работа.

.NET Framework съществува в два варианта:

-     .NET Framework – пълна версия.

-     .NET Compact Framework – съкратена версия за изпълнение върху мобилни устройства. Създадена е специално за устройства с ограни­чени хардуерни ресурси.

Visual Studio .NET 2003 представлява цялостна интегрирана среда за разработка на .NET приложения. Позволява създаване на различни видове приложения, писане на програмен код, изпълнение и дебъгване на прило­жения, изграждане на потребителски интерфейс и др. VS.NET предоставя единна среда за всички технологии и за всички програмни езици, поддър­жани стандартно от .NET Framework (C#, VB.NET, C++ и J#).

.NET Building Block Services

.NET Building Block Services са съвкупност от XML уеб услуги, насочени към крайния потребител. Основната им задача е да осигуряват персонали­зиран достъп до данните на даден потребител по всяко време и от вся­какво устройство. За целта се използват отворени стандарти и протоколи за комуникация.

.NET Building Block Services са създадени с цел да позволяват лесна интеграция с други услуги и приложения и да позволяват връзка между тях. Ето няколко области, в които има изградени такива Building Block услуги:

-     автентикация – на базата на .NET Passport

-     доставка на съобщения

-     съхранение на лични потребителски данни – документи, контакти, електронна поща, календар, любими сайтове и други

-     съхранение на настройки на приложения, които потребителят използва.

.NET Smart Clients

Smart clients представлява архитектурна концепция, която позволява из­граждането на клиентски приложения, които:

-     предоставят гъвкав потребителски интерфейс (за разлика от уеб приложенията и WAP приложенията)

-     консумират XML уеб услуги (чрез които си осигуряват връзка с останалия свят и обменят данни със сървърите, които съхраняват и обработват техните данни)

-     могат да работят в online и offline режим (като синхронизират данните си когато са online)

-     имат възможност да се самообновяват (и това може да става автома­тично, с минимални усилия от страна на потребителя).

Смарт клиентите предоставят алтерна­тива на клиент-сървър приложе­ни­ята и уеб приложенията. Като концепция те не са непременно обвързани с .NET. Има, например, реализация на smart клиент архитектури, базирани на Java платформата.

.NET платформата предоставя специализирана инфраструктура, която подпомага и улеснява реализацията на smart client приложения.

.NET smart клиентите работят както върху обикновени настолни ком­пютри, така и върху различни преносими устройства: мобилни телефони, hand held устройства, вградени системи и т. н.

Основната им задача е да предоставят достъп до информацията, нужна на потребителя, навсякъде, по всяко време и във вид, удобен за потреби­теля.

.NET Framework и неговия вариант за мобилни приложения .NET Compact Framework предлагат възможности за разработка на smart client приложе­ния за много разнообразни устройства.

Какво е .NET Framework?

До момента направихме преглед на .NET платформата и разгледахме компонентите, от които тя се състои. Сега ще разгледаме в детайли .NET Framework, неговата архитектура и модела за изпълнение на приложения, който тя използва.

.NET Framework e среда за разработка и изпълнение на приложения за .NET платформата. Тя предоставя програмен модел, библиотеки от типове и единна инфраструктура за разработка на приложения и поддържа различни езици за програмиране.

Приложенията, базирани на .NET Framework, се компилират до междинен код (на езика IL) и се изпълня­ват контролирано от средата за изпълнение на .NET Framework. Компилираният .NET код се нарича още управляван код и може да работи без да се прекомпилира върху различни платформи, за които има имплементация за .NET Framework (Windows, Linux, FreeBSD).

Компоненти на .NET Framework

Можем да разделим .NET Framework на два основни компонента:

-     Common Language Runtime (CLR) – средата, в която се изпълнява управляваният код на .NET приложенията. Представлява виртуална машина, която контролирано изпълнява .NET кода и осигурява раз­лични услуги, като управление на сигурността, управление на паметта и др.

-     Framework Class Library (FCL) – представлява основната библио­тека от типове, които се използват при изграждането на .NET приложения. Съдържа основната функционалност за разработка, необходима за пове­чето приложения, като вход/изход, връзка с бази данни, работа с XML, изграждане на уеб приложения, използване на уеб услуги, изграждане на графичен потребителски интерфейс и др. Стандартните класове и типове от FCL можем да използваме нався­къде, където има инсталиран .NET Framework.

Архитектура на .NET Framework

Архитектурата на .NET Framework често пъти се разглежда на нива, както това е направено на следната схема:

Ще разгледаме отделните слоеве един по един и ще обясним тяхната роля в .NET Framework. Ще започнем от най-долния.

Операционна система

Операционната система управлява ресурсите, процесите и потребителите на машината. Тя предоставя и някои услуги на приложенията като например: COM+, MSMQ, IIS, WMI и други.

Средата, която изпълнява .NET приложенията (CLR), е обикновен процес в операционната система и се управлява от нея, както останалите процеси.

Най-често операционната система, която изпълнява CLR е Microsoft Windows, но .NET Framework има имплементации и за други операционни системи (например проектът Mono).

Common Language Runtime

Общата среда за изпълнение Common Language Runtime (CLR) управлява процеса на изпълнение на .NET код. Тя се грижи за заделяне и освобож­даване на паметта, управлява конкурентността, грижите за сигурността на приложенията и изпълнява други важни задачи, свързани с изпълнението на кода. Ще обърнем специално внимание на CLR малко по-нататък.

Base Class Library

Base Class Library (BCL) е част от стандартната библиотека на .NET Framework – Framework Class Library (FCL).

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

Технологиите ADO.NET, XML, ASP.NET и Windows Forms не са част от BCL, тъй като те са по-скоро допълнителни библио­теки, отколкото базова системна функционалност.

ADO.NET и XML

Слоят на ADO.NET и XML предоставя удобен начин за работа с релационни и други бази от данни и средства за обработка на XML. ADO.NET поддържа два моделa на работа с данни – свързан и несвързан. XML поддръжката реализира DOM модела и модел, подобен на SAX, за достъп до XML. Ще разгледаме в детайли XML и ADO.NET в темите "Работа с XML" и "Достъп до данни с ADO.NET".

ASP.NET и Windows Forms

ASP.NET и Windows Forms изграждат слоя за интерфейс към крайния пот­ре­бител на приложенията и ни предоставят богата функционалност за създаване на уеб и Windows базиран потребителски интерфейс, както и уеб услуги. ASP.NET позво­лява по лесен начин да бъдат изграждани гъв­кави динамични уеб сайтове и уеб приложения и уеб услуги. Windows Forms позволява изграждане на прозоречно-базиран графичен потреби­телски интерфейс с богати възмож­ности.

ASP.NET и Windows Forms използват компонентно-базирана архитектура и благодарение на нея позволяват изграждане на потребителския интер­фейс визуално, чрез сглобяване на компоненти в специално разработени за това редактори, предоставени от средите за разработка. Ще разгле­даме в детайли технологиите Windows Forms и ASP.NET в темите "Графи­чен потребителски интерфейс с Windows Forms", "Изграждане на уеб приложения с ASP.NET" и "Уеб услуги с ASP.NET".

Езици за програмиране

.NET Framework позволява на разработчика да използва различни езици за програми­ране, както и да интегрира в едно приложение компоненти, разработвани на различни езици. Възможно е дори клас, написан на един език, да бъде наследен и разширен от клас, написан на друг език.

Microsoft .NET Framework поддържа стандартно езиците C#, VB.NET, Managed C++ и J#, но трети доставчици предлагат допълнително .NET версия на още много други езици, като Pascal, Perl, Python, Fortran, Cobol и други.

Съвместимостта на езиците за програмиране в .NET Framework се дължи на архитектурни решения, които ще разгледаме в детайли след малко.

Common Language Runtime

След като се запознахме накратко с архитектурата на .NET Framework, нека сега разгле­даме в детайли и най-важният компонент от нея – CLR.

Common Language Runtime (CLR) е сърцето на .NET Framework. Той пред­ставлява среда за контролирано изпълнение на управляван код. На практика CLR е тази част от .NET Framework, която изпълнява компили­раните .NET програми в специална изолирана среда.

В своята същност CLR представлява виртуална машина, която изпълнява инструкции, на езика IL (Intermediate Language), езикът до който се компилират всички .NET езици. CLR е нещо като виртуален компютър, който обаче не изпълнява асемблерен код за процесор Pentium, AMD или някакъв друг, а IL код.

Има голямо сходство между .NET CLR и Java Virtual Machine, но между двете технологии и много разлики. По предназначение те служат за едно също нещо – да изпълняват код за някакъв виртуален процесор. В .NET това е IL кода, а при Java платформата – т. нар. Java bytecode. Основната разлика между IL и bytecode е, че IL е език от по-високо ниво, а това позволява да бъде компилиран много по-ефективно от Java bytecode.

Задачи и отговорности на CLR

Отговорностите на CLR включват:

-     Изпълнение на IL кода. Реално IL инструкциите, преди да бъдат изпълнени за първи път, се компилират до инструкции за текущия процесор и след това се изпълняват от системния процесор. Този процес на междинно компилиране до машиннозависим (native) код се нарича JIT компилация (Just-In-Time compilation).

-     Управление на паметта и ресурсите на приложенията. CLR включва в себе си система за заделяне на памет и система за почистване на неизползваната памет и ресурси (т. нар. garbage collector). Управ­лението на паметта при .NET приложенията се извършва в голяма степен авто­матизирано и в повечето случаи програмистът не трябва да се грижи за освобождаване на заделената памет. Ще разгледаме в детайли как .NET Framework управлява паметта в темата "Управ­ление на паметта и ресурсите".

-     Осигуряване безопасността на типовете. .NET Framework е среда за контролирано изпълнение на програмен код (managed execution environment). Тя не позволява директен достъп до паметта, не позволява директна работа с указатели, не позволява преобразуване от един тип към друг, който не е съвмес­тим с него, не позволява излизане от границите на масив, както и всякакви други опасни операции. По тази причина .NET се нарича управля­вана среда – защото тя управлява изпълнението на кода и по този начин предпазва програмите от много досадни проблеми, които възникват при неуправляваните среди.

-     Управление на сигурността. NET Framework има добре изградена концеп­ция за сигурност на различни нива. От една страна .NET приложенията могат да се изпълняват с различни права. Правата могат да се задават от администраторите чрез т. нар. политики за сигур­ност. CLR следи дали кодът, който се изпълнява, спазва зада­дената политика за сигурност и не позволява тя да бъде нарушена. Тази техника се нарича "code access security". От друга страна .NET Framework поддържа и средства за управление на сигурността, бази­рана на роли (role-based security). Ще разгледаме в детайли всички тези техники и средства в темата "Сигурност в .NET Framework".

-     Управление на изключенията. .NET Framework е изцяло обектно-ориен­тирана среда за разработка и изпълнение на програмен код. В нея механизмът на изключенията е залегнал като основно средство за управление на грешки и непредвидени ситуации. Една от зада­чите на CLR е да се грижи за изключенията, които възникват по време на изпълнение на кода. При настъпване на изключение CLR има грижата да намери съответния обработчик и да му предостави управлението. Ще разгледаме в детайли всичко това в темата "Управление на изключенията в .NET".

-     Управление на конкурентността. CLR контролира паралелното изпълнението на нишки (threads) като за целта си взаимодейства с операци­онната система. Повече за работата с нишки ще научим в темата "Многонишково програмиране и синхронизация".

-     Взаимодействие с неуправляван код. CLR осигурява връзка между управляван (.NET) код и неуправляван (Win32) код. За целта той изпълнява доста сложни задачи, свързани с конвертиране на данни, синхронизация, прехвърляне на извиквания, взаимодействие с компонентния модел на Windows (COM) и много други. Ще разгле­даме в детайли тези проблеми в темата "Взаимодействие с неуправ­ляван код".

-     Подпомагане процесите на дебъгване (debugging) и оптими­зиране (profiling) на управлявания код. CLR осигурява инфра­структура и средства за реализацията на дебъгване и оптими­зиране на кода от външни специализирани програми.

Управляван код

Управляваният код (managed code) е кодът, който се изпълнява от CLR. Той представлява поредица от IL инструкции, които се получават при компилацията на .NET езиците. По време на изпълнение управлява­ният код се компилира допълнително до машиннозависим код за текущата платформа и след това се изпълнява директно от процесора.

Управляван код и неуправляван код

Управляваният код (.NET код) се различава значително от неуправля­вания код (например Win32 кода).

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

Неуправ­лява­ният код е машиннозависим, компилиран за определена хардуерна архи­тектура и определен процесор. Например програмите, написани на езика C, се компилират до неуправляван код за определена архитектура.

Ако компилираме една C програма за Embedded Linux върху плат­форма StrongARM, ще получим неуправляван машиннозависим (native) код за Linux за тази платформа. Кодът ще съдържа инструкции за мик­ропро­цесор StrongARM и ще използва системни извиквания към операци­онната система Embedded Linux. Съответно на друга платформа няма да може да работи без прекомпилация на сорс кода на C програмата.

По същия начин, ако компилираме една C програма за Windows върху архитектура x86, ще получим неуправляван код за процесор x86 (при­мерно Pentium, Athlon и т.н.), който използва системни извиквания към Windows. Този код се нарича Win32 код и може да работи само върху 32-битова Windows операционна система. За да се стартира върху друга платформа, трябва да се компилира.

При управлявания код нещата стоят по различен начин. Ако компилираме една C# програма за платформа .NET Framework 1.1, ще получим управ­ляван, машиннонезависим IL код, който може да работи върху разли­чен хардуер. Кодът реално ще е компилиран за платформа CLR 1.1 и ще се състои от IL инструкции за виртуалния процесор на CLR и ще използва системни извиквания към .NET Base Class Library.

Управляваният код лесно може да бъде пренесен върху различни плат­форми без да се променя или прекомпилира. Така например програма на C#, която е компилирана под Windows до управляван IL код, може да се изпълнява без промени както върху Windows под .NET Framework, така и върху Linux под Mono, а също и върху мобилни устройства под Windows CE и .NET Compact Framework.

Метаданните в управлявания код

Управляваният код се самоописва чрез метаданни и носи в себе си опи­сание на типове данни, класове, интерфейси, свойства, полета, методи, пара­метри на мето­дите и други, както и описание на библиотеки с типове, описание на изисквания към сигурността при изпълнение и т. н. Това дава голяма гъвкавост на разработчика и възмож­ност за динамично зареждане, изследване и изпълнение на функционалност, компилирана като управля­ван (IL) код.

Неуправляваният код стандартно не съдържа метаданни и това силно затруднява динамичното зареждане и изпълнение на неуправлявана функционалност.

Управляваният код е обектно-ориентиран

Управляваният код задължително е обектно-ориентиран, докато за неуп­равлявания няма такова изискване. Всички .NET езици са обектно-ориентирани. Всички .NET програми се компилират до класове и други типове от общата система от типове на .NET Framework. Всички данни, използвани от управлявания код, са наследници (в смисъла на обектно-ориентираното програмиране) на базовия тип System.Object. Ще разгле­даме това в подробности в темата "Обща система от типове".

Управляваният код е високо надежден

Управляваният код е защитен от неправилна работа с паметта и типо­вете и това го прави по-сигурен и високо надежден. Управляваният код не може да извършва неправилен достъп до паметта, достъп до чужда памет и неправилна работа с типове. Това предпазва програмисти от много досадни проблеми, присъщи при писането на неуправляван код, като загуба на памет, достъп до неинициализирана памет, повторно осво­бождаване на памет, работа с невалиден указател и т.н.

Управляваният код интегрира различни езици

До управляван код се компилират всички .NET езици. Това дава възмож­ност за широко взаимодействие между код, писан на различни езици за програмиране. Възможно е дори клас, написан на един .NET език, да бъде наследен и разширен от клас, написан на друг .NET език.

За .NET Framework няма значение на какъв език е бил написан кода преди да бъде компилиран. Всичкият код се компилира до IL и се изпълнява от CLR по еднакъв начин.

Управление на паметта

Управлението на паметта е една от важните задачи на CLR. Идеята за автоматизирано управление на паметта е залегнала в .NET Framework на дълбоко архитектурно ниво. Целта е да се улесни разработчика като се освободи от досадната задача сам да следи за освобождаването на заделената памет.

CLR, като средата за изпълнение, управлява заделянето на памет, иници­ализирането й, и автоматичното й освобождаването посредством garbage collector.

Динамично заделените обекти се разполагат в динамичната памет, в тъй наречения "managed heap". След като техния живот завърши и те вече не са необходими на приложението, системата за почистване на паметта (garbage collector) освобождава заеманата от тях памет автоматично. По този начин се избягват най-често срещаните проблеми като загуба на памет и достъп до освободена или неинициализирана памет. Повече за управлението на паметта в .NET Framework ще научим в темата "Управление на паметта и ресурсите".

Важна особеност при работата с управляван код е, че при него няма указатели. Вместо указатели се работи с референции, които са силно типизирани и се управляват автоматично. Референцията (reference) прилича на указател, но не е просто адрес в паметта, а има тип, т. е. тя е указател към определен тип данни и не може да сочи към място в паметта, където няма инстанция на този тип.

Intermediate Language (IL)

Междинният език Intermediate Language (IL), е език за прог­рамиране от ниско ниво, подо­бен на асемблерните езици. За разлика от тях, обаче, IL е от много по-високо ниво, отколкото асемблерите за съвременните мик­ропроцесори.

IL е обектно-ориентиран език. Той разполага с инструкции за заделяне на памет, за създаване на обект, за предизвикване и обработка на изклю­чения, за извикване на виртуални методи и други инструкции, свързани с обектно-ориентираното програмиране.

Тъй като не е процесорно-специфичен, IL предос­тавя голяма гъвкавост и възможност за изпълнение на кода върху различни платформи чрез компилиране до съответния за платформата машинен език.

Възможна е и предварителна компилация до код за текущата платформа, но тази техника не носи голяма полза и рядко се използва.

Имплементацията на IL в .NET Framework се нарича MSIL (Microsoft Intermediate Language). IL може да има и други имплементации в други платформи и среди за изпълнение на .NET код.

Езикът IL е стандартизиран от организацията ECMA и в съответния стан­дарт се нарича CIL (Common Intermediate Language).

Често пъти термините IL и MSIL се използват като взаи­мозаменяеми и затова винаги трябва да имате предвид, че става въпрос за кода, който се изпълнява от CLR – ма­шинният код, получен при компилацията на .NET езиците.

Intermediate Language (IL) – пример

За да илюстрираме по-добре казаното до тук, нека разгледаме една проста програмка, написана на MSIL – класическият пример "Hello world!":

.method private hidebysig static void Main() cil managed

{

  .entrypoint

  // Code size       11 (0xb)

  .maxstack  8

  ldstr    "Hello, world!"

  call     void  [mscorlib]System.Console::WriteLine(string)

  ret

} // end of method HelloWorld::Main

Всичко, което прави тази MSIL програма, е да изведе съобщението "Hello, world!" на конзолата. Тя дефинира един статичен метод без параметри с име Main, в който извиква с параметър "Hello, world!" статичния метод WriteLine() от класа System.Console, който отпечатва посочения текст.

Компилация и изпълнение

Вече споменахме няколко пъти междинния код IL и обяснихме, че .NET езиците (C#, VB.NET и т. н.) се компилират до него, а след това получе­ният код се изпълнява от CLR.

Сега ще разгледаме детайлно процеса на компилиране и изпълнение на .NET приложенията. Ще изясним как се извършва компилирането на програми от високо ниво, как се получава IL код, как този код се записва в специален файлов формат (асембли) и как след това компилираните асемблита се изпълняват от CLR като се компилират междувременно до машинен код от JIT компилатора.

Целият този процес е изобразен схематично на фигурата:

Изходният код на .NET програмите може да е написан на предпочитания от нас .NET език, например C#, VB.NET, Managed C++ или друг. За да го компилираме до IL управляван код, използваме компилатора за съответ­ния език. В резултат получаваме асембли.

Асемблито представлява изпълним файл, съдържащ .NET управляван код и метаданни, които описват съдържанието на асемблито. Метаданните съдържат имената на класовете и типовете в асемблито, информация за членовете на класовете (методи, полета, свойства и други).

Едно асембли може да бъде изпълним файл (.exe файл) или динамична библиотека (.dll файл). Изпълнимите файлове съдържат допълнителна информация, която подпомага началното им стартиране (например входна точка на изпълнение).

При изпълнение на дадено асембли CLR го зарежда в паметта и анализира метаданните му. Извършват се различни проверки на кода – дали е коректен спрямо IL стандарта, дали има необходимите права за изпъл­нение и др.

След това управляваният IL код преминава през специфичния за текущата платформа JIT компилатор и се компилира до машинен код за текущия процесор. Компилираният вече код след това се изпълнява директно от процесора.

JIT компилаторът не компилира в началото цялото асембли, а само методът, от който започва изпълнението му. След това при опит за изпълнение на некомпилиран метод, той се компилира. Така кодът се компилира само при нужда и това осигурява добро бързодействие. Забавянето е незначително и скоростта на изпълнение на управлявания код на практика е почти еднаква със скоростта на изпълнение на неуправлявания код.

Предимството на JIT компилацията е, че може да оптимизира кода за текущата хардуерна платформа по най-добрия начин. Например ако е наличен най-мощният процесор на Intel или AMD и CLR поддържа този процесор, той ще компилира IL кода по начин, оптимизиран специално за него, и ще използва пълните му възможности. При неуправляваният код това не е възможно, защото кодът се компилира така, че да работи върху всички процесори, без да използва пълните възможности на текущата хардуерна платформа. По тази причина в някои случаи управляваният код може да е дори по-бърз от неуправлявания въпреки нуждата от JIT компилация, която отнема време.

Когато разполагаме с компилирано асембли и искаме да го изпълним, имаме право на избор кога да компилираме IL кода до машинен код. Това може да стане по време на изпълнение (посредством JIT компилатора) и предварително (с прекомпилация за текущата платформа).

Прекомпилацията на асемблита се извършва с инструмента ngen.exe, който е стандартна част от .NET Framework.

Архитектура на CLR

Общата среда за изпълнение CLR се състои от доста модули, всеки от които изпълнява конкретна задача. Схематично архитектурата можем да представим по следния начин:

Ще разгледаме всеки от посочените компоненти съвсем накратко, тъй като функциите им са от много ниско ниво и рядко ще ни се налага да взаимодействаме директно с тях:

-     Base Class Library Support – предоставя системни услуги, необходими за работата на Base Class Library (BCL).

-     Thread Support – предоставя услуги за манипулация на нишки в .NET приложенията – създаване на нишка, управление на състоянието на нишка, синхронизация и др.

-     COM Marshaler – грижи се за комуникацията с COM обекти. Осигу­рява извикването на COM сървъри от .NET код и извикването на .NET код от COM. Негова грижа са прехвър­лянето на заявки, преобра­зуването на данни, управлението на жизнения цикъл на COM обектите и др.

-     Type Checker – осъществява проверка на типовете за съответствие при извикване и поддържа класовите йерархии.

-     Exception Manager – грижи се за управление на изключенията –предизвикване на изключение, прихващане, обработване и др.

-     Security Engine – отговаря за проверките на сигурността при изпъл­нение на кода.

-     Debug Engine – осигурява функционалност, свързана с дебъгването и оптимизирането на управляван код.

-     JIT Compiler – един от най-важните модули – по време на изпъл­нение компилира IL кода в специфичен за процесора код.

-     Code Manager – управлява изпълнението на кода.

-     Garbage Collector – управлява паметта автоматичното почистване на паметта и ресурсите. Контролира живота на обектите.

-     Class Loader – служи за зареждане на класове и типове. Използва се при началното изпълнение на приложението, както и при динамично зареждане на код по време на изпълнение.

Как CLR изпълнява IL кода?

Нека сега разгледаме по-подробно как CLR изпълнява IL кода. Изпълне­нието на кода, както можем да видим от схемата по-долу, е итеративен процес, който се състои от много стъпки.

При изпълнение на метод от едно асембли Class Loader подсистемата на CLR зарежда всички нужни за неговата работа класове и типове. В зависимост от това дали кодът е вече компилиран до машинен или не Class Loader предава кода за директно изпълнение или го компилира с JIT компила­тора (при първо извикване на всеки метод).

Преди JIT компилацията се извършва процес, известен като верификация. Той проверява дали IL кодът е безопасен – дали не се опитва да осъществява директен достъп до паметта, дали не се опитва да заобикаля механизмите за сигурност и т. н. Ако системният администратор е определил кода за сигурен (trusted) неговото верифициране може да бъде се прескочено.

JIT компилаторът създава специфичен за машината код (native код), който се изпъл­нява директно от процесора. Този машинен код съдържа в себе си много допълнителни инструкции, чрез които си взаимодейства със CLR. Целта е кодът да се изпълнява по контролиран начин, за да не нарушава принципите за сигурност и надеждност, но без да се забавя излишно заради всички допълнителни проверки.

При изпълнението на кода, при достъп до ресурси, при извикване на системни библиотеки и в много други случаи се извършват проверки на сигурността (чрез т. нар. security engine).

Ако трябва да бъде извикан некомпилиран метод, този метод се връща в JIT компилатора и така се затваря цикълът на компилация до машинен код. Като резултат от описания алгоритъм не се налага компилиране на един и същ метод повече от веднъж и освен това, ако някой метод не се извиква никъде в приложението, той въобще не се компилира от JIT компилатора.

Асемблита

Асемблитата са най-малката самостоятелна градивна единица в .NET Framework. Те представляват наследници на познатите ни .exe и .dll файлове и съдържат IL изпълним код, метаданни и ресурси:

За разлика от неуправляваните изпълними файлове, асемблитата са самоописващи се и носят в себе си информация за всички класове, типове и ресурси, които съдържат, както и информация за сигурността, за зависимост от външни компоненти и др. Тази информация се нарича метаданни.

Асемблитата имат собствена версия и дефинират изисквания към правата, свързани със сигурността, на потребителя или процеса, който ги изпъл­нява. Те могат да имат и цифров подпис, положен от създателя им, чрез който се осигурява повишена сигурност.

Проблемът "DLL Hell"

С вграждането на версия в самия файл на асемблито се разрешава проблемът, известен като "DLL Hell". Той се състои в следното: Когато няколко приложения зависят от един и същ споделен файл и от точно определена негова версия, с досегашните технологии в Windows при поява на нова версия на този файл, старият файл се презаписва и на практика няма гаранция, че новата версия е 100% съвместима със ста­рата. В резултат по "магически" начин някое от приложенията, което е изпол­звало старата версия, престава да работи.

Например при Win32 приложенията може да се случи при инсталиране на нов софтуер част от старите приложения, които са работели до този момент, да спрат да работят. Причината е в това, че новият софтуер презаписва някоя от библиотеките, които старите приложения са изпол­звали, с по-нова версия, която може да не е съвместима със старата.

Тъй като при асемблитата версията се задава за всяко едно от тях и се записва освен в метаданните на асемблито и в неговото файлово име, при поява на нова версия не се появяват конфликти между приложенията.

Всяко асембли може да посочи точно кое асембли му е необходимо и точно в коя негова версия. Освен, че могат да съществуват едновременно няколко различни версии на едно асембли, те могат и да се изпълняват едновременно. Така е възможно в един и същи момент да работят и старите и новите приложения и всяко приложение да използва версията на общите асемблита, с която е предвидено да работи.

Всяко асембли съдържа т. нар. манифест, в който се описват зависи­мостите, които има с други асемблита. В него се определя и политиката за избор на версия, в случай че има повече от една за някое от реферира­ните асемблита.

Метаданни

Както вече споменахме, всички асемблита съдържат метаданни. Мета­данните описват различни характеристики на асемблитата и съдържимото в тях:

-     име на асемблито (например System.Windows.Forms)

-     версия, състояща се от 4 числа (например 1.0.5000.0)

-     локализация, описваща език и култура (например неутрална или en-US или bg-BG)

-     цифров подпис на създателя (незадължителен)

-     изисквания към правата за изпълнение

-     зависимости от други асемблита (описани с точното име и версия)

-     експортирани типове

-     списък със дефинираните класове, интерфейси, типове, базови класове, имплементирани интерфейси и т.н.

-     списък с дефинираните ресурси

Освен тези данни за всеки клас, интерфейс или друг тип, който е дефиниран в асемблито, се съдържа и следната информация:

-     описание на член-променливите, свойствата и методите в типовете

-     описание на параметри на методите, връщана стойност на метода за всеки метод

-     приложени атрибути към асемблито, методите и другите елементи от кода

IL код

Във всяко асембли може да има секция, в която се намира неговият из­пълним код (IL кодът). Тази секция не е задължителна. Вече разгледахме какво представлява IL кодът и как се изпълнява, така че няма да се спираме отново на това.

Ресурси

В ресурсната секция на асемблито могат да бъдат добавяни различни ресурси (иконки, картинки, локализирани низове и др.), необходими на приложението. Ресурсите могат да се пакетират във файла на асемблито, заедно с изпълнимия код и могат да се извличат от него по време на изпълнение. Тази секция не е задължителна.

За удобство имаме възможност да създаваме и асемблита, които се състоят от няколко файла, както и сателитни асемблита с различна култура. Ще разгледаме асемблитата по-детайлно в темата "Асемблита и разпространение".

Разгръщане на асемблита

Тъй като асемблитата са основната единица за разгръщане (deployment) в .NET Framework, ще се спрем накратко върху различните видове асемблита според начина им на разгръщане – частни и споделени.

Частните асемблита (private assemblies) се използват само от едно приложение и се записват в неговата директория или в нейна поддиректория. Те са лесни за разгръщане тъй като могат да се разпрост­раняват чрез просто копиране и вмъкване (copy/paste). При тях контролът на версиите е по-лесен и не се изисква цифров подпис на създателя или силно име.

Споделените асемблита от своя страна са достъпни за всички приложения. Те се инсталират в специална област, наречена Global Assembly Cache (GAC). Всяко приложение, което реферира външно асембли търси споделените асемблита в тази област. Това поведение може да се контролира чрез манифеста, който задава правилата за търсене на нужните асемблита и версии. За да се определи уникално всяко асембли използва т. нар. силно име (strong name). To включва:

-     име на асемблито

-     версия

-     локализация

-     цифров подпис на създателя

Пример за силно име на асембли е идентификаторът:

["myDll, Version=1.0.0.1, Culture=neutral, PublicKeyToken= 9b35aa32c18d4fb1"]

Повече за разгръщане на приложения и асемблита можете да намерите в темата "Асемблита и разпространение".

.NET приложения

.NET приложенията се състоят от едно или повече асемблита, в които се съдържат техният код и ресурси. Те пред­став­ля­ват изпълними единици, които могат да бъдат конфигурирани.

В зави­симост от вида си .NET приложенията могат да бъдат самостоятелни или обвързани с други услуги или приложения. Например уеб приложе­нията не са самостоятелни и се изпълняват в средата на ASP.NET, докато конзолните приложения могат да се изпълняват самостоятелно.

За разлика от повечето Win32 приложения, .NET приложенията могат да бъдат инсталирани с просто копиране (XCOPY deployment), без да се налага регистриране на отделните им компоненти (регистрирането се налага само, ако искаме да позволим неуправлявани компоненти да могат да достъпват нашите асемблита). При .NET приложенията не се използва Windows Registry за регистрация на компонентите.

Всяко приложение използва собствена политика за зареждане на свър­заните с него асемблита и намирането на нужната им версия. При липса на изрично указана такава първо се търси подходящо асембли в дирек­ториите на приложението и после в GAC. Всяко едно приложение може да използва различна версия на дадено асембли без да се влияе от останалите и, както вече споменахме, новите версии не предизвикват конфликти.

Поради всички посочени качества инсталирането, поддържането, обновя­ването и деинсталирането на .NET приложения е лесно и безопасно за останалите приложения.

Преносими изпълними файлове

В Windows и в .NET Framework се въвежда понятието "преносим изпълним файл" (Portable Executable или PE). Това са файлове, които съдържат информация за себе си, съдържат своя изпълним код и необходимите за работата си ресурси. Структурата на РЕ файловете може да се онагледи със следната фигура:

РЕ хедърът съдържа описание за вида на самия РЕ файл – дали той е изпълним или е библиотека с типове.

След него CLR хедърът дава нужната на CLR информация за изпълнение на самото асембли.

Останалите елементи са ни вече познати от структурата на асемблитата и затова няма да се спираме на тях отново.

Понятието РЕ представлява обобщение на двата файлови формата – .exe и .dll (става дума единствено за Windows платформи – при другите имплементации на CLI е много вероятно тези формати да се описват по друг начин.)

Application domains

Application domain (домейн на приложението) е ново понятие, което се въвежда с .NET Framework. То представлява допълнително ниво на изо­лация между отделни .NET приложения, изпълнявани в един и същ процес на опера­ци­онната система.

За да се ограничат възможните проблеми, свързани с манипулиране на паметта, в операционната система всеки процес разполага със собствена памет, с която работи, и няма право да чете или пише в паметта на друг процес. Ако се налага такова взаимодействие, то се извършва индиректно например чрез прокси обекти.

Както вече знаем, всяко .NET приложение изисква CLR да бъде зареден в паметта. Ако трябва да го зареждаме за всяко .NET приложение, което старти­раме, това ще предизвика голямо ненужно натоварване и неефек­тивно използване на ресурсите.

Като решение на този проблем идва концепцията за обединяване на няколко .NET приложения в един процес от операционната система. Това, обаче крие рискове приложенията да си пречат едно на друго. Необходим е начин за изолиране на приложенията едно от друго в рамките на процеса. Точно такава е задачата на домейните на приложенията (application domains) – те ни позволяват да изпълняваме няколко прило­же­ния в един и същ процес и същевременно ни дават пълна изолация между тях. По този начин намаляваме броя на процесите, спестяваме разход на процесорно време за зареждане на CLR и прехвърляне между процесите и намаляваме количеството на използваната памет и елимини­раме повторното зареждане на едни и същи библиотеки.

.NET Framework използва вътрешно домейни на приложението за много цели, например за да изолира едно от друго отделните ASP.NET уеб при­ло­жения в рамките на един уеб сървър.

Интеграция на езиците за програмиране

Една от най-добрите черти на .NET Framework е възможността за интегра­ция на множество езици за програмиране. Тя позволява да рабо­тим на предпочитания от нас език и да не губим възможността за изпол­зване на други езици в рамките на нашето решение.

За .NET Framework няма значение на какъв език е написан даден клас или компонент, стига езикът да поддържа общата езикова спецификация – CLS (Common Language Specification), т.е. да е един от .NET езиците.

Интеграцията на различни езици в .NET Framework е възможна благо­да­рение на три важни стандарта:

-     Common Language Specification (CLS)

-     Intermediate Language (IL)

-     Common Type System (CTS)

Ще разгледаме тези стандарти един по един с изключение на IL, тъй като вече се запознахме с него.

Common Language Specification (CLS)

CLS дефинира общите и задължителни характеристики, които един прог­рамен език трябва да притежава, за да бъде съвместим с останалите .NET езици. Тази спецификация има за цел да минимизира разликите между .NET езиците.

CLS, например, налага ограничението да се прави разлика межди малки и главни букви в имената на типовете и техните публични членове, методи, свойства и събития. Ако нарушим това правило, нашият код ще се компи­лира, но ще загуби съвместимостта си с CLS и другите .NET езици.

Друго ограничение, което CLS налага, e езиците да бъдат обектно-ориен­тирани. Това означава, че за да бъде направен даден език съвместим с CLS и .NET Framework, той трябва да бъде разширен да поддържа класове, интерфейси, свойства, изключения и всички останали елементи на обектно-ориентираното програмиране с .NET.

Повечето .NET езици поддържат много повече възможности от тези, които изисква CLS. Поради това трябва да сме внимателни при създаването на класове и други типове и да подхождаме с ясната идея дали искаме те да са CLS съвместими или не.

Common Type System (CTS)

Общата система от типове в .NET Framework представлява формална спецификация на типовете данни, използвани в различните .NET езици за програмиране. CTS описва различните .NET типове (примитивни типове данни, класове, структури, интерфейси, делегати, атрибути и др.). В CTS се описват съдържанието и начина на дефиниране на типовете, модифи­каторите за достъп, начините за наследяване, времето на живот на обектите и много други технически характеристики.

CTS ни гарантира съвместимостта на данните между отделните езици за програмиране. Например типът String в С# е същия като String във Visual Basic .NET. Това позволява кодът, писан на различни езици, да си обменя свободно данни, защото данните са съвместими с CTS.

CTS дефинира двата типа обекти – референтни и стойностни, според това как се пазят в паметта и как се манипулират. CTS налага задълже­нието всички типове да наследяват системния тип System.Object, дори и примитивните. Благодарение на това извикването "5.ToString()" е на­пълно валидно в езика C#.

Ще опишем съвсем накратко референтните и стойностните типове в CTS, а в по-големи детайли относно тях ще навлезем в темата "Обща система от типове".

Референтни типове

Референтни типове (reference types) са всички класове, масиви, интер­фейси и делегати. Класът String също е референтен тип. Техните инстан­ции представляват типово-обезопасени указатели към паметта, в която са записани данните за определен обект.

Инстанциите на референтните типове се съхраняват в динамичната памет (managed heap) и подлежат на почистване от системата за събиране на боклука (garbage collector). При предаване като параметър, те се преда­ват по референция (адрес).

Стойностни типове

Стойностни типове (value types) са структурите и примитивните типове (като int, float, char и други). Този тип обекти се съхраняват в стека и се унищожават при излизане от обхват. При предаване като параметър, се предават по стойност (освен, ако изрично не е указано друго).

Common Language Infrastructure (CLI)

Спецификацията за общата инфраструктура на .NET езиците CLI (Common Language Infrastructure) е стандартизираната част от CLR. Нейната цел е още по-мащабна от идеята да се интегрират различните езици за програмиране – става дума за междуплатформена съвместимост. За целта тя е стандартизирана от организациите ECMA и ISO (стандарт ISO 23271:2003).

В CLI се описва как приложения написани на различни езици да могат да се изпълняват в различни среди без да се налага да се променят или прекомпилират.

CLI стандартизира следните компоненти на .NET Framework:

-     Common Language Specification (CLS)

-     Common Type System (CTS)

-     Common Intermediate Language (CIL)

-     Начина за управление на изключения в .NET

-     Форматите за асемблита и метаданни

-     Части от .NET Framework Class Library

Имплементацията на CLI стандарта за Windows е Microsoft .NET Framework, а за UNIX и Linux е Mono. С учебна цел Майкрософт разпространяват официално имплементация на CLI с отворен код, т. нар. Shared Source CLI (http://msdn.microsoft.com/net/sscli/).

.NET езиците

Microsoft предлагат компилатори и поддръжка във Visual Studio .NET 2003 за следните езици:

-     C# - препоръчителният език за програмиране под .NET Framework. Съвременен обектно-ориентиран език, подобен на C++ и Java, раз­работен специално за .NET Framework.

-     Visual Basic .NET – обновена версия на езика Microsoft Visual Basic, адаптирана към .NET Framework.

-     C++ (managed/unmanaged)езикът C++ по идея е език от доста по-ниско ниво в сравнение със C# и VB.NET. Той е адаптиран към .NET Framework чрез множество разширения, допълнения и ограничения и е наречен Managed C++. Езикът продължава да съще­ствува и като неуправляван език, който не е съвместим с .NET и се нарича Unmanaged C++.

-     J# – езикът J# е създаден за да позволи по-лесното прехвърляне на Java приложения към C#. Той спазва синтаксиса на езика Java, на използва както стандартните библиотеки на Java платформата, така и стандартните библиотеки на .NET (Framework Class Library).

-     JScript.NET – езикът JScript.NET е представител на слабо типизи­раните скрип­тови езици от фамилията ECMAScript (като JavaScript, VBScript и JScript), но е адаптиран към .NET Framework. Използва се за изпълнение на скриптове в някои уеб браузъри и някои други приложения.

Допълнително освен стандартните .NET езици трети доставчици са разра­ботили съвместими с .NET Framework компилатори за Perl (ActiveState Perl for .NET), Python, Pascal (Borland Delphi 2005), Smalltalk, APL, COBOL, Eiffel, Haskell, Scheme и др.

Можем да използваме най-удобния ни език и да го смесваме с други езици в рамките на едно приложение. Имаме възможност да наследяваме без­проблемно типове, дефинирани на друг програмен език. Дори можем да използваме ефективно системата за изключения и тяхната обработка между езиците.

Интеграцията на езиците за програмиране в .NET Framework е вградена и не се налага да правим "акробатики" за да я използваме. Това е възможно поради единните система от типове, програмен модел и библиотеки от класове.

Езикът C#

Както вече споменахме, C# е препоръчваният език за програмиране за .NET Framework. Този език е специално проектиран от архитектите на .NET Framework и е съобразен с особеностите на платформата още по време на дизайна. Именно по тази причина в настоящата книга всички примери и програмен код са написани на C#.

C# компилаторът е част от стандартния пакет на Microsoft .NET Framework SDK. C# е нов език, който се появява за пръв път в .NET и представлява смесица между C++ и Java, с елементи от Delphi. Проектиран е от екипа на Андерс Хейлсбърг, създателят на средата за бърза разработка на при­ложения Delphi, който е работил дълги години като архитект в Borland, а по-късно се присъединява към Microsoft.

C# е съвременен обектно-ориентиран език, силно типизиран, с широка поддръжка на идеите на компонентно-ориентирания подход за разра­ботка. C# поддържа синтаксис за дефиниране и използване на свойства и събития, които играят важна роля при дефинирането и използването на компоненти.

C# е наследник на езика C++, но не наследява от него всичко, а само част от синтаксиса и някои негови силни страни (например предефи­нирането на оператори). По идея C# е проектиран да бъде лесен за използване като Java, но мощен като C++ и до голяма степен тази идея е осъществена.

В C# е премахната нуждата от допълнителни файлове като хедъри, IDL дефиниции и други, познати ни в повечето езици като C и С++. Езикът няма никакви ограничения в употребата си – еднакво добре можем да програмираме Windows, уеб или конзолни приложения, услуги (services) или библиотеки.

Заради силната типизация в С# всичко е обект – всеки един от типовете, дефинирани било в .NET Framework, било от нас, директно или индиректно наследяват базовия тип System.Object.

Самият език С# е стандартизиран от ЕСМА и ISO още преди да бъде реализирана финалната му версия в .NET Framework.

Езикът C# – пример

Както вече обяснихме, настоящата книга разглежда работата с .NET Framework в контекста на езика С#, така че от тук нататък често ще срещаме правоъгълни области с приме­рен код, като следващата:

using System;

 

namespace HelloCSharp

{

  class HelloCSharp

  {

     static void Main()

     {

       Console.WriteLine("Hello, C#!");

     }

  }

}

Примерът дефинира нашата първа програма на C# – класическата прог­рамка "Hello, World!", която е адаптирана за C# и се е превърнала в "Hello, C#!". Сега няма да обясняваме в детайли как работи тя, защото ще направим това по-късно, в темата "Въведение в C#".

Framework Class Library

Framework Class Library (FCL) е стандартната библиотека на .NET Framework. В нея се съдържат няколко хиляди дефиниции на типове, които предоставят богата функционалност.

FCL съдържа средства, които позволяват на програмистите да разработват различни видове приложения:

-     Windows приложения с прозоречно-базиран графичен потребителски интерфейс

-     Уеб-базирани приложения

-     Конзолни приложения

-     Приложения за мобилни устройства

-     XML уеб услуги

-     Windows услуги

-     Библиотеки с компоненти

Основните библиотеки, от които се състои FCL, са:

-     Base Class Library – библиотека съдържаща основните средства, нужни за разработване на приложения. Дефинира работа с вход и изход, многозадачност, колекции, символни низове и интернациона­лиза­ция, достъп до мрежови ресурси, сигурност, отдалечено извик­ване и други.

-     ADO.NET и XML – осигуряват достъп до бази данни и средства за обработка на XML.

-     ASP.NET – предоставя ни рамкова среда (framework) за разработка на уеб приложения с богата функционалност, както и средства за създаване и консумиране на уеб услуги.

-     Windows Forms – служи за основа при разработването на Windows приложения с прозоречно-базиран графичен потребителски интер­фейс. Windows Forms се базира на вградените в Windows средства за изграждане на графичен потребителски интерфейс.

По-нататък ще обърнем специално внимание на всички тези библиотеки и ще разгледаме средствата, които те предлагат, в дълбочина.

Пакетите от FCL

За да се работи по-лесно с това голяма многообразие от типове, което FCL предлага, типовете са разделени в отделни асемблита и допълнително са разпределени в пространства от имена (namespaces) според своето пред­назначение и взаимовръзка.

Да разгледаме основните пространства от имена от FCL и тяхното пред­назначение:

-     System – съдържа основни типове, използвани от всяко .NET прило­жение. В пространството System се намира, например, базовият за всички типове в .NET Framework клас System.Object, както и класът System.Console, който позволява вход и изход от конзолата.

-     System.Collections – в това пространство се намират често използвани типове за управление на колекции от обекти: стек, опашка, хеш таблица и други.

-     System.IO – съдържа типовете, които осигуряват входно-изходните операции в .NET Framework – потоци, ресурси от файловата система и други.

-     System.Reflection – съдържа типове, които служат за достъп до метаданните по време на изпълнение на кода. Чрез тях е възможна реализацията на динамично зареждане и изпълнение на код.

-     System.Runtime.Remoting – имплементира технология, която позво­лява отдалечен достъп до обекти и данни по прозрачен за програ­миста начин.

-     System.Runtime.Serialization – обединява типове, отговорни за процеса на сериализация и десериализация на обекти (запазване на състоянието на обект и по-късното му възстановяване).

-     System.Security – в това пространство се намират типовете, които се използват за управление на сигурността. Те позволяват защита на данни и ресурси, определяне и проверка на текущите права на пот­ребителя и други.

-     System.Text – типовете от това пространство предоставят функци­оналност за обработка на текст, промяна на кодовата му таблица и други услуги, свързани с конвертиране на данни и интернациона­лизация на приложенията.

-     System.Threading – дефинира типове, осигуряващи достъп до нишки и свързаните с тях операции, като например синхронизация.

-     System.Xml – съдържа типове за работа с XML и технологиите, свързани с него.

Освен тези общодостъпни пространства от имена, разполагаме и с още някои, които са достъпни за различните типове приложения:

-     System.Web.Services – дефинира типовете, използвани за изграж­да­нето и консумирането на уеб услуги.

-     System.Web.UI – съдържа стандартни средства и компоненти за изграждане на уеб приложения.

-     System.Windows.Forms – съдържа типове, използвани при създава­нето на Windows приложения с графичен потребителски интерфейс.

Visual Studio .NET

До момента се запознахме с .NET Framework, с нейната архитектура, със средата за контролирано изпълнение на управляван код CLR и с основ­ните библиотеки на .NET Framework.

Време е да разгледаме и средата за разработка на .NET приложения, която Microsoft предоставят на разработчиците. Това е продуктът Microsoft Visual Studio .NET (VS.NET).

VS.NET е една от водещите в световен мащаб интегрирани среди за разра­ботка на приложения (IDE – Integrated Development Environment). С негова помощ можем да извършваме всяка една от типичните задачи, свързани с изграж­дането на едно приложение – писане на код, създаване на потребителски интерфейс, компилиране, изпълняване и тестване, дебъгване, проследяване на грешките, създаване на инсталационни пакети, разглеждане на документацията и други.

Писане на код

Пакетът Visual Studio .NET 2003 поддържа стандартно езиците за програ­миране Microsoft C# .NET, Microsoft Visual Basic .NET, Microsoft C++ .NET (managed/unmanaged) и Microsoft Visual J#. За да ползвате език, различен от тези, които Microsoft предлага стандартно, трябва да инсталирате нуж­ните добавки към VS.NET.

Текстовият редактор за код на VS.NET поддържа всички утвърдени съвре­менни функции на редакторите за сорс код – синтактично оцве­тяване за по-лесно визуално възприемане на кода и намаляване на грешките, авто­матично довършване на започнат израз, автоматично извеждане на помощна информация по време на писане, средства за навигация по кода и много други.

Поддържа се IntelliSense функционалност за подсказване на имена на класове, методи и променливи. Тя предоставя огромно улеснение за навлизащите тепърва .NET програмисти, тъй като позволява те да разгле­дат на място възможностите и да изберат от списък тази, която ги инте­ресува. Така се спестяват усилия, време за изписване на името и се намалява значително вероятността за досадни "правописни" грешки.

Следващата илюстрация дава нагледна представа за редактора на код на Visual Studio .NET 2003:

Създаване на потребителски интерфейс

Visual Studio .NET 2003 предоставя удобен за работа графичен дизайнер за потребителски интерфейси. С него за няколко минути можем да изгра­дим дизайна на даден потребителски интерфейс, независимо дали става дума за Windows Forms прозорец, уеб страница или интерфейс за мобилни приложения.

Това, което виждаме във VS.NET докато изграждаме потребителския интер­фейс, е почти същото, което и потребителят ще види, когато стар­ти­ра приложението. Начинът на работа с различните технологии за предста­вяне на потребителски интерфейс е много подобен и това допълнително улеснява разработчиците и повишава тяхната продуктивност.

Добавянето на визуални компоненти (или потребителски контроли) става чрез влачене и пускане (drag and drop), а след това ни остава само да настроим нужните свойства на обекта със желаните от нас стойности и да добавим обработчици към някои от събитията.

Ето изглед от VS.NET в момент на редактиране на диалог от Windows Forms приложение:

Компилиране

Visual Studio .NET 2003 предлага унифициран начин за работа с компила­торите за различните езици. Не се налага да използваме командния ред и да знаем дългия списък с инструкции към компилатора за да можем да компилираме кода и да създаваме асемблита. Достатъчно е на натиснем [Shift+Ctrl+B] за да компилираме цялото решение с всички проекти в него.

При компилация VS.NET автоматично създава нужните асемблита и ресурсни файлове. Tя се грижи и за сателитните асемблита (ако има такива), опреснява референциите към външни файлове и класове и изпълнява още много други задачи.

Освен синтактичните грешки, процесът на компилация улавя и някои семантични. Допълнително той може да показва и предупредителни съобщения за съмнителен или недобър код. Можем да контролираме нивото на филтриране на тези предупреждения и дори да настроим средата да ги счита за грешки и да прекъсва процеса на компилация заради тях.

Едно ограничение, което VS.NET има, е че то не може да създава многофайлови асемблита. Ако това наистина ни се наложи трябва да използваме инструмента Assembly Linker (al.exe).

VS.NET предлага два режима на компилация:

-     Debug – в този режим компилаторът създава дебъг символи за всички методи в приложението и ги записва в отделен файл с разширение .pdb. Чрез него можем да извършваме проследяване на грешките (debugging). Този режим на компилация е препоръчителен за процеса на разработване и тестване на приложението.

-     Release – в този режим на компилация VS.NET създава код, готов за продукция и разпространение до клиентите. От него са отстранени всички функции свързани с дебъгване и тестване. Не се генерират .pdb файлове и като цяло има по-добра производителност от Debug версията. За сметка на това възможностите за откриване грешки са намалени.

Изпълняване и тестване

Тъй като Visual Studio .NET интегрира в себе си разработването на прило­жения с различни технологии, ние можем да стартираме по унифициран начин всеки един от типовете приложения. Това, което трябва да напра­вим, е единствено да натиснем бутона Start (или Debug/Start). Средата проверява дали има промени във файловете на проекта, ако има такива, тя прекомпилира приложението и след това стартира съответния процес.

VS.NET поддържа т. нар. решения (solutions). В едно решение може да има един или повече проекта. Например в една система може да 3 проекта – уеб услуга, Windows Forms клиент и ASP.NET уеб приложение.

Имаме възможност да указваме проект, който да се стартира при стартиране на решението. Допълнително можем да укажем да се стар­тират множество проекти при натискане на бутона Start. Тази опция е много удобна при разработване на клиент-сървър приложения, тъй като не ни се налага ръчно да стартираме всеки компонент.

Тестването на приложенията може да се извършва веднага след стар­тирането. Тъй като Visual Studio .NET 2003 се "закача" в дебъг режим към процеса на стартираното приложението, можем да дебъгваме лесно и бързо своя код.

Проследяване на грешки

Процесът на проследяване на грешки, или както по-често го наричаме дебъгване, се осъществява много лесно със Visual Studio .NET 2003. Средата ни предоставя множество вградени в нея инструменти, с които да извършваме тази задача. Инструментите са достъпни от менюто Debug и включват следните възможности:

-     Breakpoints – списък със зададените точки на прекъсване (break points). Можем да премахваме, създаваме и настройваме парамет­рите на всяка точка поотделно.

-     Running documents – списък с всички файлове, които се използват от приложението в момента. Използва се главно при дебъгване на уеб приложения.

-     Call stack – показва ни стекът на извикванията на методите до дадения момент. Перфектен е за анализ на програмна логика и намиране на мястото, където е възникнало изключение.

-     Autos – показва всички променливи, които са в момента в обхват.

-     Local – показва всички локални променливи.

-     Immediate/Command Window – позволява ни да изпълняваме инструкции и да променяме стойности на променливи по време на изпълнение. Предоставя множество мощни възможности, които обаче излизат извън рамките на нашата тема.

-     Watch – показва списък с всички променливи, които сме заявили, че искаме да наблюдаваме. Чрез него можем и да променяме техните стойности по време на изпълнение на програмата.

-     Quick Watch – показва стойността на избрана при дебъгване променлива.

-     Step control – дава ни средства за постъпково изпълнение на кода ред по ред и стъпка по стъпка. Можем да избираме реда на изпълне­ние; да изпълняваме методи като влизаме в тях или ги изчакваме да завършват и преминаваме към следващата стъпка; можем да контро­лираме и кои редове от кода се изпълняват и при нужда да местим курсора на изпълнение напред и назад.

-     Exception control – можем да задаваме дали нашето приложение да влиза в дебъг режим при възникване на изключение и да спира веднага след мястото на възникване на изключението без да сме сложили точка на прекъсване.

Освен тези удобства имаме възможност да разглеждаме съдържанието на паметта и регистрите в "суров" вид и да извършваме декомпилация на кода (disassembling).

Създаване на инсталационен пакет

Освен стандартните шаблони за всеки език за програмиране Visual Studio .NET 2003 ни предлага и шаблони за инсталационни пакети. Така се затваря цикълът на разработка на приложения. Можем да използваме готовите стандартни форми и технологии на инсталация и/или да добавим свои собствени към инсталационния пакет. След като сме завършили и тази стъпка, можем да разпространяваме своето приложение до крайните потребители.

Технологиите на инсталиране, които ни предлага Visual Studio .NET 2003, са приложими за почти всякакви приложения, независимо от това дали са конзолни, Windows Forms, уеб приложения или библиотеки с типове. Процеса на създаване на инсталационни пакети е разгледан подробно в темата "Асемблита и разпространение".

Получаване на помощ

При инсталиране на Visual Studio .NET с него се инсталира неговата доку­мен­тация и по желание документацията на Microsoft .NET Framework (т.нар. MSDN Library).

Те автоматично се интегрират в средата за разработка и позволяват да получим т. нар. контекстно-ориентирана помощ. Например, докато изпол­зваме даден клас от .NET Framework, VS.NET ни показва неговата доку­ментация в прозореца Dynamic Help. Интегрираната помощна система във VS.NET позволява при натискане на клавиша [F1] да получим информация за текущия клас, свойство или компонент, който е на фокус. Това значително улеснява разработчика.

VS.NET е силно разширяема среда

Интегрираната среда за разработка Microsoft Visual Studio .NET е така про­ектирана, че лесно да може да се разширява с допълнителни модули и нови възможности. Съществуват стотици добавки (plug-ins) за VS.NET, които добавят поддръжка на нови езици и нови технологии, подпомагат процеса на разработка по различни начини, добавят интеграция с други продукти и т. н. Някои от тях са свободни, докато други са комерсиални продукти. Благодарение на добре документираните програмни интер­фей­си за интеграция с VS.NET програмистите могат да добавят и собствени добавки за средата.

Упражнения

1.    Опишете накратко платформата Microsoft .NET. Кои са основните принципи, които са заложени в нея? Избройте четирите компонента, от които тя се състои.

2.    Какво представляват .NET Enterprise сървърите? Избройте някои от тях. Какво представлява .NET Framework? От какви компоненти се състои? Какво е Visual Studio .NET? За какво служат .NET Building Block услугите? Какво са .NET Smart клиентите? Какво е характерно за тях?

3.    Опишете накратко .NET Framework. От какви компоненти се състои?

4.    Какво представлява средата за контролирано изпълнение на прог­рамен код Common Language Runtime (CLR)?

5.    Какво представлява Framework Class Library (FCL)? Каква функцио­налност предлага тя?

6.    Какво е управляван код? Има ли причина да бъде използван вместо традиционния машиннозависим код? Какво е характерно за меж­динния език IL?

7.    Какво представляват .NET асемблитата (assemblies)? Каква инфор­мация съдържат метаданните в асемблитата? Какво представляват .NET приложенията? Какво е област на приложението (application domain)?

8.    Какво е Common Language Specification (CLS)? Защо е необходима тази спецификация? Какво описва тя?

9.    Какво представлява общата система от типове в .NET Framework (Common Type System)? Защо е необходима тя?

10. Избройте няколко от .NET езиците. Какво е общото между тях? Какво е специфичното за всеки от тях?

11. Избройте основните пакети от Framework Class Library (FCL). За какво служат те?

Използвана литература

1.    Светлин Наков, Архитектура на платформата .NET и .NET Framework – http://www.nakov.com/dotnet/lectures/Lecture-1-MS.NET-Framework-Architecture-v1.03.ppt

2.    Jeffrey Richter, Applied Microsoft .NET Framework Programming, Microsoft Press, 2002, ISBN 0735614229

3.    MSDN, Common Language Runtime Overview – http://msdn.microsoft.  com/library/en-us/cpguide/html/ cpconcommonlanguageruntimeoverview.asp

4.    MSDN, Compiling to MSIL – http://msdn.microsoft.com/library/en-us/ cpguide/html/cpconMicrosoftIntermediateLanguageMSIL.asp

5.    MSDN, Application Domains Overview – http://msdn.microsoft.com/ library/en-us/cpguide/html/cpconapplicationdomainsoverview.asp


 

 

 

 

 

www.devbg.org

 

 

Българска асоциация на разработчиците на софтуер (БАРС) е нестопанска организация, която подпомага про­фе­сионалното развитие на българските софтуерни специ­а­листи чрез образо­вателни и други инициативи.

БАРС работи за насърчаване обмяната на опит между раз­работ­чиците и за усъвършенстване на техните знания и умения в областта на проектирането и разработката на софтуер.

Асоциацията организира специализирани конференции, семи­нари и курсове за обучение по разработка на софту­ер и софту­ерни технологии.

БАРС организира създаването на Национална академия по раз­работка на софтуер – учебен център за професионал­на подго­товка на софтуерни специалисти.

 


Глава 2. Въведение в C#

Необходими знания

-     Добро познаване на поне един език за програмиране от високо ниво (С, С++, Java, Pascal/Delphi, Perl, Python, PHP или друг)

-     Базови познания за архитектурата на .NET Framework

Съдържание

-     Принципи при дизайна на езика

-     Нашата първа програма на C#

-     Типове данни в C#. Примитивни типове данни. Изброен тип

-     Декларации. Изрази. Оператори. Програмни конструкции

-     Елементарни програмни конструкции. Съставни конструкции

-     Конструкции за управление – условни конструкции, конструкции за цикъл, конструкции за преход. Специални конструкции

-     Коментари в програмата

-     Вход и изход от конзолата

-     Дебъгерът на Visual Studio .NET

-     XML документация в C# кода

В тази тема...

В настоящата тема ще разгледаме езика С#, ще се запознаем с неговите основни концепции, ще напишем и компилираме първата си C# програма. Ще се запознаем със средата за разработка Visual Studio .NET 2003 и ще демон­стрираме работата с нейния дебъгер. Ще отделим внимание на типовете данни, изразите, програм­ните конструкции и конструкциите за управ­ление в езика C#. Накрая ще демонстри­раме колко лесно и полезно е XML доку­ментирането на кода в С#.

Настоящата тема има за цел да запознае читателя с конкретните синтак­тични правила на езика C# и неговите програмни конструкции без да претендира за изчерпателност. В нея няма да обясняваме какво е промен­лива, функция, цикъл и т. н., а ще се фокусираме върху реализацията на тези езикови примитиви в C#. Очаква се читателят да владее основите на програ­мирането с поне един език от високо ниво, а тази тема ще му помогне да премине към C#.


Какво е C#

С# е съвременен, обектно-ориентиран и типово обезопасен език за прог­рамиране, който е наследник на C и С++. Той комбинира леснотата на използване на Java с мощността на С++.

Създаден от екипа на Андерс Хейлсбърг, архитектът на Delphi, С# заим­ства много от силните страни на Delphi – свойства, индексатори, компо­нентна ориентираност. С# въвежда и нови концепции – разделяне на типовете на два вида – стойностни (value types) и референтни (reference types), автоматично управление на паметта, делегати и събития, атрибути, XML документация и други. Той е стандартизиран от ECMA и ISO.

C# е специално проектиран за .NET Framework и е съобразен с неговите особености. Той е сравнително нов, съвременен език, който е заимствал силните страни на масово използваните езици за програмиране от високо ниво, като C, C++, Java, Delphi, PHP и др.

Принципи при дизайна на езика C#

Преди да се запознаем със синтаксиса и програмните конструкции в C#, нека първо разгледаме основните принципи, залегнали при проектира­нето му.

Компонентно-ориентиран

Езикът C# е насочен към компонентно-ориентираното програмиране, при което софтуерът се изгражда чрез съединяване на различни готови компо­ненти и описание на логиката на взаимодействие между тях.

При проектирането на .NET Framework и езика C# компо­нент­ният подход е залегнал на най-дълбоко архитектурно ниво. .NET Framework дефинира общ компонентен модел, който установява правилата за изграждане и използване на компоненти за всички .NET приложения. Езикът C# под­държа класове, интерфейси, свойства, събития и други средства за описа­ние на компонентите, както и средства за тяхното използване. В темата "Графичен потребителски интерфейс с Windows Forms" ще дискутираме по-задълбочено компонентния модел на .NET Framework.

Всички данни са обекти

С# е обектно-ориентиран език за програмиране. В него залягат основните принципи на обектно-ориентираното програмиране, като капсулация на данните, наследяване и полиморфизъм.

В .NET Framework всички типове данни наследяват системния тип System. Object и придобиват от него някои общи методи, свойства и други харак­теристики.

В следствие на това в C# всички данни се третират като обекти. Дори примитивните типове, чрез въвеждането на автоматичното им опако­ване (boxing) и разопако­ване (unboxing) се превръщат в обекти. Напри­мер, 5.ToString() е валид­но извикване в C#, защото 5 се опакова и се раз­глежда като обект от тип System.Object, на който се извиква метода ToString().

Сигурност и надеждност на кода

По идея .NET Framework и C# са проектирани за да осигурят висока сигурност и надеждност на изпълнявания софтуер. .NET Framework предо­ставя среда за контролирано изпълнение на управляван код, с което прави невъзможно възникването на някои от най-неприятните проблеми, свързани с управлението на паметта, неправилното преобразуване на типове и др. C# наследява всички тези характеристики от .NET Framework и добавя към тях някои допълнителни механизми за предпазване на програ­мистите от често срещани грешки.

Силна типизираност и типова безопасност

С# е силно типизиран и типово обезопасен. В него не се използват указа­тели към паметта, които създават много проблеми в по-старите езици за програмиране. Вместо тях се използват специални силно типизирани ука­затели, които се наричат референции (references). Използването на референции вместо указатели решава проблемите, които възникват от неправилната работа с указатели и директния достъп до паметта. В .NET Framework управлението на паметта се извършва почти изцяло от CLR.

Всъщност в C# може да се използват указатели (като тези в C и C++) чрез запазената дума unsafe, но това не е се препоръчва в масовия случай, защото лишава програмата от типова обезопасеност и позволява непра­вилна работа с паметта.

В С# не може да се излезе от границите на масив или символен низ. При опит да бъде направено това, се получава изключение, което може да бъде прихванато и обработено. В езици като C, C++ и Pascal излизането от границите на масив води до достъп до памет, използвана от други данни и най-често пъти предизвиква сривове или неочаквано поведение на програмата.

При създаване на клас, структура или друг тип C# компилаторът не позволява да останат неиници­ализирани член-данни. Това защитава прог­рамиста от възможността да работи с неинициализирани данни.

Макар С# да не инициализира авто­матично локалните променливи, ком­пилаторът предупреждава за непра­вилното им използване. Например следният код ще предизвика грешка при опит за компилация:

int value;

value = value + 5;

Преобразуването на типове също е безопасно. CLR не позволява да се извърши невалидно преобразуване на типове – да се преобразува про­менлива от даден тип към променлива от тип, който не е съвместим с първия. При опит да бъде направено това, възниква изключение.

Неявното преобразуване на типове е разрешено само за съвместими ти­пове, когато не е възможна загуба на информация. При явно преобразу­ване на типове, ако те не са съвместими, се хвърля InvalidCastException по време на изпълнение. Например следният код предизвиква изключение по време на изпълнение:

object a = "This will raise InvalidCastException!";

int b = (int) a;

Безопасност на аритметичните операции

В C# чрез запазената дума checked могат да се отделят блокове код, в които аритметичните операции се проверяват за препълване на типовете и ако това се случи, се хвърля OverflowException. Това е много полезно, защото за разлика от С++, където при такива ситуации се получава грешен резултат, в С# може да се реагира адекватно на такава специфична ситуация. Ето един пример, при който CLR засича препълване на типа int:

checked

{

  int i = 100000;

  int j = i*i; // OverflowException is thrown

}

Експлицитно задаване на виртуални методи и припокриване на метод

Една от целите на езика C# е да позволи с малко усилия да се пише надежден код. С цел да се намалят грешките от припокриване на виртуални методи са въведени запазените думи new и override, чрез които да се контролира припокриването на виртуален метод, който е в базов клас при наследяване. Каква е разликата между двете? При полиморфизъм (обект от базовия клас е създаден като обект от наследника), ако е използвана new като модификатор на метода в наследника, ще се извика функцията на базовия клас, а при използване на override – функцията на наследника.

Автоматично управление на паметта и ресурсите

В .NET Framework заделянето и използването на паметта се управлява автоматично от CLR (Common Language Runtime). Стойностните типове, които ще разгледаме по-подробно в темата "Обща система от типове", се пазят в стека, докато референтните – в т. нар. "динамична памет" (managed heap), за която се грижи системата за почистване на паметта (garbage collector).

Системата за почистване на паметта е част от CLR и нейна задача е да освобождава периодично паметта и ресурсите, заделени за обекти, които не се използват повече от приложението. Такива обекти могат да бъдат най-разнообразни: данни в динамичната памет, масиви, символни низове, а също и файлове, буфери в паметта, връзки към бази данни и др.

Грижата за паметта е трудна и сложна задача, но благодарение на CLR тя не е задължение на .NET програмистите. На нея ще обърнем специално внимание в темата "Управление на паметта и ресурсите".

Широко използване на изключения

Обработката на грешки, които могат да възникнат по време на изпъл­нение на програмата, в .NET Framework се реализира чрез използване на изключения. Механизмът на изключенията позволява да се съобщи за възникнал проблем или неочаквана ситуация и за нея да може да се реа­гира адекватно.

Изключенията представляват обекти от клас Exception или производен на него клас и съдържат информация за възникналата грешка. Напри­мер, при опит за деление на нула CLR прихваща проблема и предизвиква изключението DivideByZeroException, а при опит за излизане от грани­ците на масив възниква ArgumentOutOfRangeException. Работата с изклю­чения също ще бъде дис­кутирана в детайли в темата "Управление на изключенията в .NET".

Вградени механизми за сигурност на кода

В .NET Framework са въведени т. нар. сигурност на ниво достъп до кода (code access security) и сигурност, базирана на роли (role-based security). Чрез тях се осъществява контрол на достъпа до ресурси от програмата. Например, ако трябва да се извика системна функция или да се пише във файл, кодът трябва да има права да го направи. Сигурността на ниво достъп до кода оставя CLR да взима решения, докато при сигурност, базирана на роли, програмата може да реагира различно спрямо ролята и правата на потребителя.

Всичкият код е на едно място

В С# няма разделяне на хедър файлове и файлове с имплементация, както в C и C++. Това спестява много проблеми и улеснява поддръжката на сорс кода. В C# всичкият програмен код на даден клас е в един файл.

Програмите на C#

Програмите на С# представляват съвкупност от дефиниции на класове, структури и други типове. Във всяка C# програма някой от класовете съдържа метод Main() – входна точка за програмата.

Приложенията могат да се състоят от много файлове, а в един файл може да има няколко класове, структури и други типове.

Класовете логически се разполагат в пространства от имена (namespa­ces). Те от своя страна могат да се систематизират в йерархия, т.е. едно пространство от имена може да съдържа както класове, така и други пространства от имена. Едно пространство от имена може да е разположе­но в няколко файла и дори в няколко асемблита. Например, в простран­ството от имена System се съдържа пространството от имена Xml. Прост­ранството System.Xml от своя страна е разделено в две различни асем­блита - System.Xml.dll и System.Data.dll.

Във Visual Studio .NET има инструмент, наречен "Object Browser", чрез който могат да се разгледат йерархиите на пространствата от имена в проекта, какво съдържат те и в кои файлове се намират.

Нашата първа програма на C#

Всяка книга за запознаване с даден програмен език започва обикновено с програмката "Hello, world!". Ние няма да правим изключение от този принцип и ще започнем по подобен начин – с програмката "Hello, C#". Ето как изглежда нейният сорс код:

HelloCSharp.cs

using System;

 

class HelloCSharp

{

  static void Main()

  {

     Console.WriteLine("Hello, C#");

  }

}

Как работи програмата?

На първия ред директивата using System указва, че се използва прост­ранството от имена System (т.е. всички класове, структури и други типове, декларирани в него). Тя е като #include в C++, като import в Java и като uses в Delphi.

Следва декларацията на клас с ключова дума class. Този клас се състои от един единствен метод – методът static void Main(), който е входна точка на програмата. Когато този метод завърши, завършва и програмата.

В метода Main() се извиква метода WriteLine(…) на класа Console, нами­ращ се в пространството от имена System. Класът Console осигурява сред­ства за вход и изход от конзолата. Чрез него отпечатваме на конзолата текста "Hello, C#".

Компилиране от командния ред

Програми на C# могат да се компилират от командния ред чрез компи­латора csc.exe, който е стандартна част от .NET Framework и е достъпен от директорията, в която е инсталиран той. При стандартна инсталация тя е C:\Windows\Microsoft.NET\Framework\v1.1.4322.

Можем да компилираме сорс кода на примерната програма по след­ния начин: Използвайки командния интерпретатор (cmd.exe) се придвиж­ваме до директорията, където се намира файлът HelloCSharp.cs. След това можем да го компилираме със следната команда:

csc HelloCSharp.cs

За да бъде намерен компилаторът csc.exe, е необхо­димо в текущия път (в променливата PATH от средата) да е включена дирек­торията на .NET Framework.

Ако компилацията премине успешно, в резултат се получава файлът HelloCSharp.exe, който представлява .NET асембли, записано като изпъл­ним файл.

Стартиране от командния ред

Стартирането на получения изпълним (.exe) файл става както всички останали изпълними файлове, например чрез следната команда:

HelloCSharp.ехе

Резултатът

Резултатът от изпълнението на нашата първа C# програмка представлява един текстов ред:

Hello, C#

Резултатът от компилирането и изпълнението на примерната програма е показан на следващата картинка:

Създаване на проект, компилиране и стартиране от Visual Studio.NET

Ще покажем как може да се използва интегрираната среда за разработка на приложения Microsoft Visual Studio .NET за изпълнение на предходната примерна програмка. Ще създадем нов проект (конзолно приложение), ще го компилираме и изпълним. Трябва да преминем през следните стъпки:

1.    Стартираме Visual Studio .NET.

2.    От меню File избираме New Project. Избираме Visual C# Projects | Console Application. Избираме име и местоположение за проекта:

Visual Studio .NET създава за нас един Solution и един проект в него, съдържащ няколко файла. Файлът, в който можем да пишем нашия код, се отваря автоматично.

3.    Въвеждаме примерната програмка. Можем да сменим името на файла Class1.cs с HelloCSharp.cs чрез клавиша [F2], натиснат в момент, в който е активен файлът Class1.cs от Solution Explorer:

4.    За да компилираме, натискаме [Shift+Ctrl+B] или избираме менюто Build | Build Solution. Ето как изглежда VS.NET в този момент:

5.    За да стартираме приложението, натискаме [Ctrl+F5] или избираме от менюто Debug | Start Without Debugging. В резултат прило­жението се изпълнява в нов конзолен прозорец и след приключване на работата му VS.NET ни приканва да натиснем някакъв клавиш, за да затвори прозореца:

Можем да стартираме приложението и само с [F5], но тогава то ще се изпълни в режим на дебъгване и след приключване на работата му прозорецът, в който е изведен резултата, веднага ще се затвори и няма да го видим.

Запазени думи в C#

Езикът C# дефинира следните запазени думи, които се използват в кон­струкциите и синтаксиса на езика:

abstract

as

base

bool

break

byte

case

catch

char

checked

class

const

continue

decimal

default

delegate

do

double

else

enum

event

explicit

extern

false

finally

fixed

float

for

foreach

goto

if

implicit

in

int

interface

internal

is

lock

long

namespace

new

null

object

operator

out

override

params

private

protected

public

readonly

ref

return

sbyte

sealed

short

sizeof

stackalloc

static

string

struct

switch

this

throw

true

try

typeof

uint

ulong

unchecked

unsafe

ushort

using

virtual

void

volatile

while

 

Ще видим за какво служат повечето от тях постепенно, в процеса на запознаване с езика C#, с обектно-ориентираното програмиране в .NET Framework, с общата система от типове и в някои други теми.

Типове данни в C#

Типовете данни в C# биват два вида – типове по стойност (value types) и типове по референция (reference types). Типовете по стойност (стойностни типове) директно съдържат своята стойност и се съхраняват в стека. Те се предават по стойност. Типовете по референция (референтни типове) пред­ставляват силно типизирани указатели към стойност в динамичната памет. Те се предават по референция (адрес) и се унищожават от garbage collector, когато не се използват повече от програмата.

Типовете биват още примитивни (вградени, built-in) типове и типове, дефинирани от потребителя.

Стойностни типове (value types)

Типовете по стойност (стойностни типове) са примитивните типове, избро­е­ните типове и структурите. Например:

int i; // примитивен тип int

enum State { Off, On } // изброен тип (enum)

struct Point { int x, y; } // структура (struct)

Референтни типове (reference types)

Типовете по референция (референтни типове) са класовете, интерфей­сите, масивите и делегатите. Например:

class Foo: Bar, IFoo {...} // клас

interface IFoo: IBar {...} // интерфейс

string[] a = new string[5]; // масив

delegate void Empty(); // делегат

На всички типове в C# съответстват типове от общата система от типове (Common Type System – CTS) на .NET Framework. Например, на прими­тивния C# тип int съответства типа System.Int32 от CTS.

Примитивни типове

Примитивните типове данни в C# (built-in data types) биват:

Примитивни типове по стойност

-     byte, sbyte, int, uint, long, ulong – цели числа

-     float, double, decimal – реални числа

-     char – Unicode символи

-     bool – булев тип (true или false)

Примитивни типове по референция

-     string – символен низ (неизменима последователност от Unicode символи)

-     object – обект (специален тип, който се наследява от всички типове)

Типове дефинирани от потребителя

Типовете дефинирани от потребителя биват класове, структури, изброени типове, интерфейси и делегати:

class Foo: Bar, IFoo {...} // клас

struct Point { int x, y; } // структура

interface IFoo: IBar {...} // интерфейс

delegate void Empty(); // делегат

Вече се сблъскахме с класовете в C# в примерната програма "Hello, C#". Повече за тях, както и за структурите и интерфейсите ще научим в темата "Обектно-ориентирано програмиране в .NET".

Преобразуване на типовете

Има два типа преобразувания на примитивните типове – преобразуване по подразбиране (implicit conversion) и изрично преобразуване (explicit conversion).

В C# преобразуването по подразбиране е позволено, когато е безопасно. Например, от int към long, от float към double, от byte към short:

short a = 10;

int b = a; // implicit type conversion from short to int

Изричното преобразуване се използва, когато преобразуваме към по-малък тип или типовете не са директно съвместими. Например, от long към int, от double към float, от char към short, от int към char, от sbyte към uint:

int a = 10;

short b = (short) a; // explicit type conversion

В С# има специална ключова дума checked, която указва при препълване да се получава System.OverflowException вместо грешен резултат. Клю­човата дума unchecked действа противоположна на checked. Ето пример за преобразуване на типове с използване на тези ключови думи:

byte b8 = 255;

short sh16 = b8; // implicit conversion

int i32 = sh16; // implicit conversion

float f = i32; // implicit - possible loss of precision!

double d = f; // implicit conversion

checked

{

  byte byte8 = (byte) sh16; // explicit conversion

  // OverflowException is possible!

  ushort ush16 = (ushort) sh16; // explicit conversion

  // OverflowException is possible if sh16 is negative!

}

unchecked

{

  uint ui32 = 1234567890;

  sbyte sb8 = (sbyte) ui32; // explicit conversion

  // OverflowException is not thrown in unchecked mode

}

Изброени типове (enumerations)

Изброените типове в C# се състоят от множество именувани константи. Дефинират се със запазената дума enum и наследяват типа System.Enum. Ето пример за изброен тип, който съответства на дните от седмицата:

public enum Days

{

  Saturday,

  Sunday,

  Monday,

  Tuesday,

  Wednesday,

  Thursday,

  Friday

};

Изброените типове се използват за задаване на една измежду няколко възможности. Вътрешно се представят с int, но може да се зададе и друг числов тип.

Изброените типове са силно типизирани – те не се превръщат в int, освен експлицитно.

Ето пример как може да бъде използван даден изброен тип:

Days today = Days.Friday;

if (today == Days.Friday)

{

  Console.WriteLine("Днес е петък.");

}

Както се вижда, инстанциите на изброените типове могат да приемат една от дефинираните в тях стойности.

Изброените типове могат да се използват и като съвкупност от битови флагове чрез атрибута [Flags]. Ето пример за изброен тип, който може да приема за стойност комбинация от дефинираните в него константи:

[Flags]

public enum FileAccess

{

    Read = 1,

    Write = 2,

    Execute = 4,

    ReadWrite = Read | Write

}

 

// ...

 

Console.WriteLine(

    FileAccess.ReadWrite | FileAccess.Execute);

 

// The result is: "ReadWrite, Execute"

Какво представляват атрибутите и как се използват ще разгледаме по-детайлно в темата "Атрибути". Засега трябва да знаем, че чрез тях може да се асоциира допълнителна информация към типовете.

Използването на изброени типове осигурява по-високо ниво на абстрак­ция и по този начин сорс кодът става по-разбираем и по-лесен за под­дръжка.

В .NET Framework широко се използват изброени типове. Например, из­броения тип ConnectionState, намиращ се в пространство от имена System.Data, характеризира състоянието на връзка към база от данни, създадена чрез ADO.NET (зададено е и числовото съответствие на всяко едно от състоянията):

public enum ConnectionState

{

  Closed = 0,

  Open = 1,

  Connecting = 2,

  Executing = 4,

  Fetching = 8,

  Broken = 16

}

Идентификатори

Идентификаторите в С# се състоят от последователности от букви, цифри и знак за подчертаване като винаги започват с буква или знак за подчер­таване. В тях малките и главните букви се различават. Иденти­фикаторите могат да съдържат Unicode символи, например:

int алабала_портокала = 42;

bool \u1027\u11af = true;

Microsoft препоръчва се следната конвенция за именуване:

-     PascalCase – за имена на класове, пространства от имена, структури, типове, методи, свойства, константи

-     camelCase – за имена на променливи и параметри

Въпреки, че е възможно, не се препоръчва да се използват идентифика­тори на кирилица или друга азбука, различна от латинската.

Декларации

Декларациите на променливи в C# могат да са няколко вида (почти като в C++, Java и Delphi) – локални променливи (за даден блок), член-промен­ливи на типа и константи. Ето пример:

int count;

string message;

Член-променливите могат да имат модификатори, например:

public static int mCounter;

Константи

Константите в С# биват два вида – константи, които приемат стойността си по време на компилация (compile-time константи) и такива, които получават стойност по време на изпълнение на програмата (runtime константи).

Compile-time константи

Compile-time константите се декларират със запазената дума const. Те задължително се инициализират в момента на декларирането им и не могат да се променят след това. Те реално не съществуват като промен­ливи в програмата. По време на компилация се заместват със стойността им. Например:

public const double PI = 3.1415926535897932;

const string COMPANY_NAME = "Менте Софт";

Runtime константи

Runtime константите се декларират като полета с модификатора readonly. Представляват полета на типа, които са само за четене. Инициализират се по време на изпълнение (в момента на деклариране или в конструктора на типа) и не могат да се променят след като веднъж са инициализирани. Например:

public readonly DateTime NOW = DateTime.Now;

Оператори

Операторите в С# са много близки до операторите в C++ и Java и имат същите действие и приоритет. Те биват:

-     Аритметични: +, -, *, /, %, ++, --

-     Логически: &&, ||, !, ^, true, false

-     Побитови операции: &, |, ^, ~, <<, >>

-     За слепване на символни низове: +

-     За сравнение: ==, !=, <, >, <=, >=

-     За присвояване: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

-     За работа с типове: as, is, sizeof, typeof

-     Други: ., [], (), ?:, new, checked, unchecked, unsafe

В C# операторите могат да се предефинират. В темата "Обектно-ориенти­рано програмиране в .NET" ще видим как точно става това.

Изрази (expressions)

Програмен код, който се изчислява до някаква стойност, се нарича израз (expression). Изразите в C# имат синтаксиса на C++ и Java. Например:

a = b = c = 20; // израз със стойност 20

(а+5)*(32-a)%b  // израз с числова стойност

"ала" + "бала" // символен израз (string)

Math.Cos(Math.PI/x) // израз с реална стойност

typeof(obj) // израз от тип System.Type

(int) arr[idx1][idx2] // израз от тип int

new Student() // израз от тип Student

(currentValue <= MAX_VALUE) // булев израз

Програмни конструкции (statements)

Програмните конструкции (statements) имат синтаксиса на C++ и Java. Те биват няколко вида:

Елементарни програмни конструкции

Елементарните програмни конструкции са най-простите елементи на прог­рамата. Например:

// присвояване (<променлива> = <израз>)

sum = (a+b)/2;

 

// извикване на метод

PrintReport(report);

 

// създаване на обект

student = new Student("Светлин Наков", 3, 42688);

Съставни конструкции

Съставните програмни конструкции се състоят от няколко други конструк­ции, оградени в блок. Например:

{

  Report report = GenerateReport(period);

  report.Print();

}

Програмни конструкции за управление

Конструкциите за управление, както в повечето езици за програмиране, биват условни конструкции, конструкции за цикъл, за преход и т. н. В C# синтаксисът на тези конструкции е много близък до синтаксиса на C++ и Java.

Условни конструкции (conditional statements)

Условните конструкции в С# са if, if-else и switch. Техният синтаксис е еднакъв със синтаксиса им в C, C++ и Java.

if и if-else конструкциите за разлика от С и С++ могат да приемат единствено булево условие. Не са позволени целочислени стойности, които да играят ролята на true, ако са различни от 0 и false – иначе. Ето няколко примера за условна конструкция:

if (orderItem.Ammount > ammountInStock)

{

  MessageBox.Show("Not in stock!", "error");

}

 

if (Valid(order))

{

  ProcessOrder(order);

}

else

{

  MessageBox.Show("Invalid order!", "error");

}

Ново в switch конструкцията за разлика от C и C++ е, че позволява изразът, по който се осъществява условието, да бъде от тип string или enum. Например:

switch (characterCase)

{

  case CharacterCasing.Lower:

     text = text.ToLower();

     break;

  case CharacterCasing.Upper:

     text = text.ToUpper();

     break;

  default:

     MessageBox.Show("Invalid case!", "error");

     break;

}

Конструкцията switch се различава от реализацията си в С++. В С# не се раз­решава "пропадане" (fall-through). Пропадането в switch кон­струк­циите може да доведе до грешки. Независимо от удобствата, които предлага тази възможност, дизайнерите на езика С# са преценили, че рискът за грешка поради пропускане на break е по-голям, затова всеки case етикет трябва задължително да завършва с break.

Конструкции за повторение и цикъл

Конструкциите за повторение (iteration statements) са for-цикъл, while-цикъл, цикъл do-while и цикъл foreach – за обработка на колекции. Техният синтаксис е еднакъв със синтаксиса им в C, C++ и Java. Изключение прави foreach цикълът, който няма еквивалент в C и C++. Ето няколко примера:

Пример за for-цикъл:

// Отпечатваме числата от 1 до 100 и техните квадрати

for (int i=1; i<=100; i++)

{

  int i2 = i*i;

  Console.WriteLine(i + " * " + i + " = " + i2);

}

Пример за while-цикъл:

// Изчисляваме result = a^b

result = 1;

while (b > 0)

{

  result = result * a;

  b--;

}

Пример за цикъл do-while:

// Четем символи до достигане на край на ред

do

{

  ch = ReadNextCharacter(stream);

}

while (ch != '\n');

Операторът foreach е приложим за масиви, колекции и други типове, които поддържат интерфейса IEnumerable или имaт метод за извличане на итератор (enumerator).

Пример за цикъл foreach:

string[] names = GetNames();

 

// Отпечатваме всички елементи на масива names

foreach (string name in names)

{

  Console.WriteLine(name);

}

Конструкции за преход

Конструкциите за преход в C# са: break, continue – които се използват в цикли, goto за безусловен преход и return – за връщане от метод. Те работят по същия начин, като в C, C++ и Java.

Пример за използване на конструкцията break:

// Търсим позицията на даден елемент target в масива a[]

int position = -1;

for (int i=0; i<a.length; i++)

{

  if (a[i] == target)

  {

     position = i;   

     break;

  }

}

return position;

Конструкции за управление на изключенията

Конструкциите за управление на изключенията в С# са: throw – за предизвикване на изключение, try-catch – за прихващане на изключе­ние, try-finally – за сигурно изпълнение на завършваща секция и try-catch-finally – за прихващане на изключение със завършваща секция.

Пример за предизвикване и прихващане на изключение:

// ...

public static void ThrowException()

{

  // ...

  throw new System.Exception();

}

// ...

public static void Main()

{

  try

  {

     ThrowException();

  }

  catch(System.Exception e)

  {

     // ...

  }

  finally

  {

     // ...

  }

}

Методът ThrowException() предизвиква изключение от тип Exception, което може да бъде прихванато, ако функцията, която го предизвиква, се намира в try-catch блок. В такъв случай може да се извършат действия в catch блока, в зависимост от информацията, която носи това изключение.

Конструкциите try-finally и try-catch-finally се използват най-вече за освобождаване на ресурси, които се използват в тялото им. Независимо дали възникне изключение при работата с даден ресурс, той трябва да бъде освободен накрая – това обикновено се прави във finally блок, който се изпълнява независимо дали се минава през catch блока. Блокът finally се изпълнява дори и да има return в catch или try блок.

В темата "Управление на изключенията в .NET" ще разгледаме подробно работата с изключения, техните особености и препоръките за правилна работа с тях.

Специални конструкции

Специалните конструкции в С# са: lock – за синхронизирано изпълнение, checked, unchecked – за контрол на аритметичните препълвания, unsafe – за директен достъп до паметта чрез указатели, fixed – за фиксиране на местоположението в паметта при работа с неуправляван код.

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

Коментарите биват два вида - коментар за част от програмен ред и блоков коментар.

Ето пример за коментар на един ред:

Order orders[]; // Съдържа всички поръчки на потребителя

Ето пример и за блоков коментар:

/* Изтриваме всички поръчки, за които някой артикул не

е наличен в необходимото количество. Изтриване реално

не се извършва, а само се променя статуса на Canceled */

foreach (Order order in customer.Оrders)

{

  if (!AllItemsInStock(order))

  {

     order.Status = OrderStatus.Canceled;

  }

}

Вход и изход от конзолата

В .NET Framework за вход и изход от конзолата се използват стандартни класове от BCL (Base Class Library). Входът и изходът от конзолата се осъществяват чрез класа Console, намиращ се в пространство от имена System.

Класът System.Console предоставя основната функционалност, от която се нуждаят конзолните приложения (console applications), които четат и пишат на екрана. Ако конзолата не съществува (например в Windows Forms и уеб-базираните приложения), писането в конзолата няма никакъв ефект и не се предизвикват изключения.

Всяко конзолно приложение при стартиране получава от операционната система три стандартни потока – за вход, изход и за грешки. При изпълнение от конзолата тези три потока автоматично се асоциират със самата нея. За достъп до стандартния вход, стандартния изход и стандарт­ния изход за грешки в .NET Framework се използват свойствата In, Out и Error на класа Console.

Вход от конзолата

Входът от конзолата се осъществява чрез два метода на класа Console - Read() и ReadLine(). Методът Read() чете единичен символ от стандарт­ния вход и го връща като int стойност или връща -1, ако няма повече символи. Методът ReadLine() чете цял символен ред и връща string или стойност null ако е достигнат края на входа.

И двата метода са синхронни (блокиращи) операции т. е. при извикване блокират, докато не бъде прочетен някакъв символ (ред).

Методът Read() има една особеност – той не връща управлението след всеки въведен символ, а връща прочетените символи наведнъж един след друг едва след като се натисне [Enter]. По тази причина този метод не е удобен за интерактивен вход от клавиатурата при конзолни приложения.

Вход от конзолатапримери

Ето един пример за използването на метода Read():

while (true)

{

  int i = Console.Read();

  if (i == -1)

  {

     break;

  }

  char c = (char) i;

  Console.WriteLine ("Echo: {0}", c);

}

В практиката за въвеждане на стойности от конзолата по-често се изпол­зва методът ReadLine(). Ето пример за неговата употреба:

string s = Console.ReadLine();

Console.WriteLine("You enetered: {0}", s);

Изход към конзолата

Изходът към конзолата се осъществява чрез два метода на класа Console - Write(…) и WriteLine(…), които печатат на конзолата подадените като параметри данни, с разликата, че  WriteLine(…) преминава на нов ред след като отпечата текста. Методите приемат string, int, float, double и други типове данни.

Write(…) и WriteLine(…) приемат и параметрични форматиращи низове, които позволяват печатане на текст чрез шаблони, които се попълват от подадените параметри. На форматиращите низове ще обърнем специално внимание в темата "Символни низове".

Изход на конзолатапример

Ето един пример за вход и изход от конзолата, който илюстрира и изпол­зването на форматиращи низове:

int a = Int32.Parse(Console.ReadLine());

int b = Int32.Parse(Console.ReadLine());

Console.WriteLine("{0} + {1} = {2}", a, b, a+b);

// (въвеждаме съответно 2 и 3 като вход от конзолата)

// Резултат: 2 + 3 = 5

 

Console.WriteLine(

  "Днес е {0:dd.MM.yyyy} г.", DateTime.Now);

// Резултат: Днес е 13.05.2004 г.

 

Console.WriteLine("Цена: {0,12:C}", 27);

// Резултат: Цена:     27,00 лв

// (точният формат зависи от текущите езикови настройки)

 

string name = Console.ReadLine();

Console.WriteLine("Хей, {0}, часът е {1:HH:mm}!",

  name, DateTime.Now);

// (въвеждаме "Наков")

// Резултат: Хей, Наков, часът е 16:43!

Дебъгерът на Visual Studio .NET

Сега ще илюстрираме как се използва дебъгерът на Visual Studio .NET. Ще покажем поставяне на точка за спиране (breakpoint), изпълнение на прог­рамата в дебъг режим, проследяване на изпълнението на програмата и следене на стойностите на променливите по време на изпълнение.

Ще си поставим за задача да напишем програма, която намира всички трицифрени числа, сумата от цифрите на които е стойността 25. Можем да решим задачата по следния начин:

Digits.cs

using System;

 

public class Digits

{

  static void Main()

  {

     for (int d1=1; d1<=9; d1++)

     {

       for (int d2=0; d2<=9; d2++)

       {

          int d3 = 25 - d1 - d2;

          if ((d3 >= 0) && (d3 <= 9))

          {

            int n = d1*100 + d2*10 + d3;

            Console.WriteLine(n);

          }

       }

     }

  }

}

За да проследим изпълнението на примерната програма, ще изпълним следните стъпки:

1.    Стартираме Visual Studio .NET.

2.    Създаваме ново конзолно приложение с име Digits.sln. Въвеждаме в него сорс кода от примера Digist.cs.

3.    За да го компилираме натискаме [Shift]+[Ctrl]+[B].

4.    Слагаме точка на прекъсване (breakpoint) с мишката върху първия ред от най-вътрешния програмен блок (щракваме малко вляво от самия ред и редът се маркира по специфичен начин):

5.    Стартираме програмата от съответния бутон за стартиране от лен­тата с инструменти на Visual Studio .NET. Програмата ще започне да се изпълнява и когато се достигне реда с точката на прекъсване, Visual Studio .NET ще спре изпълнението и ще влезе в дебъг режим.

6.    От менюто Debug можем да разгледаме по-интересните функции на дебъгера на Visual Studio .NET. Можем да добавим точки на прекъс­ване (breakpoints), да следим стойностите на променливите, да проследяване на изпълнението на кода по различен начин (Step Into, Step over, Step out), да добавим променливи за следене (Add Watch), да следим стека за изпълнение на програмата и т.н. Можем да разгледаме представянето на променливите в паметта – като изберем Debug | Windows | Memory. Много полезен е и прозорецът Command Window, в който не само може да се види стойност на променлива в дебъг режим, но и да се изпълни някакъв метод и да се види върнатата от него стойност. С [Shift] + [F9] при маркирана променлива може да се извика прозорец за нейното наблюдение (Quick Watch).

Точките на прекъсване могат да бъдат асоциирани с някакво условие (conditional breakpoints) и да спират изпълнението на програмата само ако това условие е истина.

Ето как изглежда работното пространство на Visual Studio .NET по време на проследяване на изпълнението на програмата след спиране в точката на прекъсване и преминаване към следващия оператор с [F10]:

Инструментът ILDASM

Всяка програма на С# се компилира до междинен език IL (Intermediate Language). Microsoft предоставя стандартен инструмент за разглеждане на този, генериран от компилаторите на С#, код. Това е инструментът Microsoft .NET Framework Disassembler (ILDASM). С тази деасембли­раща про­гра­ма можем да отворим всяко .NET асембли и да разгледаме неговите пространства от имена, класове, типове и код.

Инструментът ildasm.exe е стандартна част от Microsoft .NET Framework SDK. Обикновено .NET Framework SDK идва заедно с Visual Studio .NET и се намира в директория C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin. Нека илюстрираме как се използва той. За целта трябва да изпълним следните стъпки:

1.    Стартираме командния интерпретатор cmd.exe:

Start | Programs | Accessories | Command Prompt

2.    Отиваме в директорията, където се намира компилираната прог­рама, например, програмата от предходния пример Digits.exe:

cd "C:\DotNet-course-lectures\Lecture-2-Introduction-to-CSharp\Demo-3-Digits\bin\Debug"

3.    Извикваме от командната линия инструмента ILDASM (ildasm.exe) и му подаваме като параметър компилираната програма Digits.exe:

ildasm Digits.exe

4.    Навигирайки по дървото, което ILDASM показва за асемблито Digits.exe, можем да видим как изглежда MSIL кодът за конструк­тора на класа Digits и за метода му Main():

XML документация в C#

XML документацията в C# програмите представлява съвкупност от комен­тари, започващи с ///. Тя може да съдържа различни XML тагове – напри­мер, таг описващ връщана стойност на метод, таг за препратки към други методи и др. Като идея XML документацията прилича на JavaDoc в Java.

XML документацията значително улеснява поддръжката – документацията е част от кода, а не стои във външен файл. Поддържа се лесно и ползата от нея е видима още при разработката на приложението – Visual Studio .NET показва краткото описание на даден метод, ако той е документиран чрез вградената XML документация, при задействане на IntelliSense. C# компилаторът може да извлича XML документацията като XML файл за по-нататъшна обработка.

Ето пример за използване на XML документация:

/// <summary>

/// The main entry point for the application.

/// </summary>

/// <param name="args">The command line arguments</param>

static void Main(string[] args)

{

  // ...

}

 

/// <summary>Calculates the square of a number</summary>

/// <param name="num">The number to calculate</param>

/// <returns>The calculated square</returns>

/// <exception cref="OverflowException">Thrown when the

/// result is too big to be stored in an int</exception>

/// <seealso cref="System.Int32" />

public static int square(int num)

{

  // ...

}

Тагове в XML документацията

Ето по-важните тагове, използвани в XML документацията в C#:

-     <summary>…</summary> – кратко описание за какво се отнася даден тип, метод, свойство и т.н. Visual Studio .NET показва това описание при задействане на IntelliSense.

-     <remarks>…</remarks> – подробно описание на даден тип, метод, свойство и т.н. Visual Studio .NET  показва това описание в областта Object Browser.

-     <param name="…">…</param> – описание на един от параметрите на даден метод.

-     <returns>…</returns> – описание на връщаната от даден метод стойност.

-     <exception cref="…">…</exception> – описание на изключение, което може да възникне в даден метод.

-     <seealso cref="…"/> – препратка към информация, свързана с текущото описание.

-     <value>…</value> – описание на свойство (property).

Извличане на XML документация от C# сорс код

Сега ще покажем как чрез C# компилатора може да се извлече докумен­тацията от C# файл в отделен XML файл. Нека имаме следната програма на C#, която използва XML документация:

MainClass.cs

using System;

 

namespace XMLCommentsDemo

{

  /// <summary>

  /// MainClass is a sample illustrating how to use XML

  /// documentation in C#.

  /// </summary>

  class MainClass

  {

     /// <summary>Calculates the square of a number</summary>

     /// <param name="num">The number to calculate</param>

     /// <returns>The calculated square</returns>

     /// <exception cref="OverflowException">Thrown when the

     /// result is too big to be stored in an int</exception>

     /// <seealso cref="System.Int32" />

     public static int Square(int num)

     {

       checked

       {

          return num*num;

       }

     }

 

     /// <summary>

     /// The main entry point for the application.

     /// </summary>

     /// <param name="args">The command line arguments</param>

     static void Main(string[] args)

     {

       Console.WriteLine("3*3 = " + Square(3));

     }

  }

}

За да извлечем документацията от тази програма, трябва да изпълним следните стъпки:

1.    Стартираме командния интерпретатор cmd.exe:

Start | Programs | Accessories | Command Prompt

2.    Отиваме в директорията, където се намира сорс кода на програмата. Нека тя е Demo-6-XML-Comments:

cd "C:\DotNet-course-lectures\Lecture-2-Introduction-to-CSharp\Demo-6-XML-Comments"

3.    Извикваме компилатора на C#, за да компилира файла MainClass.cs, като му задаваме опцията за извличане на XML доку­ментацията в отделен файл:

csc MainClass.cs /doc:MainClassComments.xml

4.    Отваряме получения .xml файл с Internet Explorer, за да разгледаме съдържанието му.

Ето как полученият XML файл:

MainClassComments.xml

<?xml version="1.0"?>

<doc>

  <assembly>

     <name>MainClass</name>

  </assembly>

  <members>

     <member name="T:XMLCommentsDemo.MainClass">

       <summary>

       MainClass is a sample illustrating how to use XML

       documentation in C#.

       </summary>

     </member>

     <member name="M:XMLCommentsDemo.MainClass.Square(

          System.Int32)">

       <summary>Calculates the square of a number</summary>

       <param name="num">The number to calculate</param>

       <returns>The calculated square</returns>

       <exception cref="T:System.OverflowException">Thrown when

       the result is too big to be stored in an int</exception>

       <seealso cref="T:System.Int32"/>

     </member>

     <member name="M:XMLCommentsDemo.MainClass.Main(

          System.String[])">

       <summary>

       The main entry point for the application.

       </summary>

       <param name="args">The command line arguments</param>

     </member>

  </members>

</doc>

Генериране на HTML документация от VS.NET

Сега ще покажем как чрез Visual Studio .NET може да се генерира HTML документация за даден проект на C# по XML коментарите в неговия сорс код. Във вид на HTML документацията е много по-удобна за четене и разглеждане.

За целта трябва да изпълним следните стъпки:

1.    Отваряме с Visual Studio .NET проект, в който сме използвали XML документиране, например проекта Demo-6-XML-Comments.sln, който съдържа кода от предходния пример.

2.    От меню Tools избираме Build Comment Web Pages…. Указваме директория, където да се генерира HTML документацията, и натискаме бутона [OK]. Visual Studio .NET ще генерира в посочената директория съвкупност от HTML файлове, които доку­ментират нашия проект и съдържат XML коментарите от сорс кода му, подре­дени в подходящ за разглеждане вид.

3.    Разглеждаме HTML документацията, която Visual Studio .NET е гене­ри­рал. Можем да навигираме по пространствата от имена, типовете от проекта и отделните му методи:

Директиви на предпроцесора

Нека сега разгледаме някои по-важни директиви на т. нар. предпроцесор. Преди компилация C# програмите преминават през процес на обработка, който идентифицира кода, който трябва да бъде компилиран при условна ком­пилация. Този процес се изпълнява от предпроцесора. Програмно върху предпроцесора можем да указваме влияние чрез т.нар. директиви – запазени думи, започващи със символа #.

Директиви за форматиране на сорс кода

В С# са въведени директиви за форматиране на сорс кода - #region и #endregion, които ограждат блок от кода, който се "свива" от редактора на Visual Studio .NET:

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()

{

  // ...

}

#endregion

Visual Studio .NET редакторът много често слага региони, за да отдели автоматично-генерирания код от сорс кода, писан от програмиста. Дирек­тивите #region и #endregion се игнорират от C# компилатора и се използват единствено от средите за разработка.

Директиви за условна компилация

Директивите #define и #ifdef служат за условна компилация. Чрез тях може да се укаже на компилатора да компилира кода по различен начин според процесора, платформата и въобще средата, в която се извършва компилацията. Чрез #if, #else, #elif, #endif се задават границите на блоковете за условна компилация и съответните условия (знаци) за ком­пилиране. Директивите #define и #undef дефинират знаци за услов­на компилация, според които се определя кой от блоковете за условна компилация да се разглежда.

Условна компилация – пример

Следният пример показва как могат да се използват директивите на предпроцесора за условна компилация:

#define DEBUG

#define VC_V7

 

using System;

public class MyClass

{

  public static void Main()

  {

#if (DEBUG && !VC_V7)

     Console.WriteLine("Only DEBUG is defined");

#elif (!DEBUG && VC_V7)

     Console.WriteLine("Only VC_V7 is defined");

#elif (DEBUG && VC_V7)

     Console.WriteLine("DEBUG and VC_V7 are defined");

#else

     Console.WriteLine("DEBUG and VC_V7 are not defined");

#endif

  }

}

Ето и резултата от изпълнението на примера:

Директиви за контрол над компилатора

Директивите #warning и #error предизвикват предупреждения и грешки по време на компилация. Например следната програма на C# се компи­лира успешно, но с предупреждение:

#define DEBUG

public class MyClass

{

  public static void Main()

  {

#if DEBUG

#warning DEBUG symbol is defined

#endif

  }

}

Документацията на .NET Framework

Програмирането с .NET Framework е немислимо без неговата документа­ция. Затова нека сега разгледаме какво представлява тя и как можем да я използваме при търсене на помощна информация по време на разработ­ката на .NET приложения.

MSDN Library

Документацията на .NET Framework се съдържа в "Microsoft MSDN Library".

MSDN Library е система, която предоставя пълен набор от технически до­кументи, описващи продуктите, инструментите и технологиите за разра­ботка на Microsoft (в частност .NET Framework и C#), както и средства за навигация и търсене в тях. MSDN Library съдържа технически ръковод­ства, справочна информация, статии, при­мери и други ресурси за софту­ерни разработчици.

MSDN Library е достъпен безплатно в on-line вариант от Интернет сайта за разработчици на Microsoft – http://msdn.microsoft.com/library/. Продуктът се разпростра­нява и за локална инсталация заедно с партньорските прог­рами на Microsoft.

MSDN Library – пример

За пример ще покажем как можем да намерим подробна информация за форматиращите низове в .NET Framework и тяхното използване. За целта стартираме MSDN Library и търсим "composite formatting":

.NET Framework и MSDN Library

Документацията на .NET Framework е част от MSDN Library и се разпро­странява заедно с VS.NET и .NET Framework SDK.

Когато бъде инсталирана, документацията за .NET Framework, тя се инте­грира във VS.NET и може да се използва директно от него. Напри­мер, ако се нуждаем от помощна информация за метода WriteLine(…) на класа Console, натискаме [F1] във Visual Studio .NET докато курсорът е върху този метод. Отваря се нов прозорец, в който са описани параметрите, типа на връщаната стойност, типовете изключения, които може да предиз­вика описвания метод, в кое пространство от имена се намира и др.

Ето как изглежда описанието на метода WriteLine(…) на класа Console:

Упражнения

1.    Съставете програма на C#, която въвежда от конзолата име на студент и го поздравява в стил "Здравей, <име>!".

2.    Съставете програма на C#, която въвежда коефициентите на квад­ратно уравнение и пресмята реалните му корени.

3.    Напишете програма, която намира всички символни низове, които се състоят от точно 5 малки латински букви и са симетрични спрямо сре­дата си.

4.    Проследете работата на програмата от задача 3 с дебъгера на Visual Studio .NET.

5.    Променете програмата от задача 3, така че да намира само тези низове, които съдържат четен брой гласни букви. Колко са тези низове?

6.    Добавете XML документация в програмата от задача 5 и генерирайте HTML документация от Visual Studio .NET.

7.    Напишете програма, която намира сумарната стойност на група фактури. Програмата трябва да въвежда последователно от конзолата сумите на фактурите (реални числа със знак) докато стигне до празен ред. Сумарната стойност на фактурите трябва да се отпечата в 10-символно поле, дясно подравнена, с точност 2 знака след десетичната запетая (потърсете в документацията подходящ форматиращ стринг).

8.    Напишете програма, която прочита прост числен израз, състоящ се от реални числа, свързани с операциите "+" и "-", и изчислява и отпе­чатва стойността му.

Използвана литература

1.    Светлин Наков, Въведение в C# – http://www.nakov.com/dotnet/ lectures/Lecture-2-Introduction-to-CSharp-v1.0.ppt

2.    MSDN Training, Programming C#  (MOC 2124C), Module 2: Overview of C#

3.    MSDN Training, Programming C#  (MOC 2124C), Module 3: Using Value-Type Variables

4.    Jessy Liberty, Programming C#, Second Edition, O’Reilly, 2002, ISBN 0-596-00309-9

5.    Svetlin Nakov, .NET Framework Overview – http://www.nakov.com/ publications/Nakov-DotNET-Framework-Overview-english.ppt

6.    MSDN, C# Keywords – http://msdn.microsoft.com/library/en-us/csref/ html/vclrfcsharpkeywords_pg.asp

7.    MSDN, C# Built-in Types Table – http://msdn.microsoft.com/library/en-us/csref/html/vclrfbuiltintypes.asp

8.    MSDN, Common Type System Overview – http://msdn.microsoft.com/ library/en-us/cpguide/html/cpconcommontypesystemoverview.asp

9.    MSDN, Enumerations –  http://msdn.microsoft.com/library/en-us/cpguide/ html/cpconEnumerations.asp

10. MSDN, C# Operators – http://msdn.microsoft.com/library/en-us/csref/ html/vclrfCSharpOperators.asp

11. MSDN, Statements (C# Programmer's Reference) – http://msdn.microsoft.com/library/en-us/csref/html/vclrfstatements.asp

12. MSDN, XML Documentation Tutorial (C# Programmer's Reference) – http://msdn.microsoft.com/library/en-us/csref/html/vcwlkxmldocumentationtutorial.asp

13. MSDN, C# Preprocessor Directives - http://msdn.microsoft.com/ library/en-us/csref/html/vclrfPreprocessorDirectives.asp

14. MSDN, Composite Formatting – http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcompositeformatting.asp

15. MSDN, Console Class (.NET Framework) – http://msdn.microsoft.com/ library/en-us/cpref/html/frlrfsystemconsoleclasstopic.asp


Глава 3. Обектно-ориентирано програмиране в .NET

Необходими знания

-     Познаване на принципите на обектно-ориентираното програ­миране

-     Познаване на поне един обектно-ориентиран език за програ­миране – C++, Java, C#, Object Pascal/Delphi

Съдържание

-     Предимства и особености на ООП.

-     Основни принципи на ООП. Основни понятия

-     ООП и .NET Framework

-     Членове на клас

-     Член-променливи (полета). Константни полета

-     Методи (член-функции)

-     Статични членове

-     Конструктори. Статичен конструктор

-     Предаване на параметрите

-     Свойства. Индексатори

-     Предефиниране на оператори

-     Наследяване

-     Интерфейси. Абстрактни класове

-     Виртуални членове. Предефиниране и скриване.

-     Клас диаграми

-     Принципи при обектно-ориентирания дизайн

-     Пространства от имена (namespaces)

В тази тема ...

В настоящата тема ще направим кратък обзор на основните принципи на обектно-ориентираното програмиране (ООП) и сред­ствата за изпол­зването им в .NET Framework и езика C#. Ще се запознаем с типовете "клас", "струк­тура" и "интерфейс" в C#. Ще въведем понятието "член на тип" и ще се разгледаме видовете членове (член-променливи, методи, конструк­тори, свойства, индексатори и др.) и тяхната употреба. Ще се спрем и на наследяването на ти­по­ве в различните му аспекти и приложения. Ще обърнем внимание и на полиморфизмът в C# и свързаните с него понятия и програмни техники. Накрая ще обсъдим някои утвър­дени практики при създаването на ефек­тив­ни йерархии от типове.


Предимства и особености на ООП

Обектно-ориентираното програмиране се е наложило като стандарт при почти всички съвре­менни езици за програмиране. То предоставя мощно средство за модели­ране на обектите от реалния свят и взаимоотношени­ята между тях, позволява добро структу­риране на програмния код и улес­нява неговото преизползване. Благода­рение на капсулацията на данните, чрез която се скриват импле­ментационните детайли и се намалява слож­ността на софтуера, както и на възможностите за наследяване на свойства и действия и за работа с абстракт­ни данни и изпълнение на абстрактни операции, ООП е се е утвърдило като предпочитан подход при създаване на големи приложения и библиотеки.

Моделиране на обекти от реалния свят

В основата на ООП стоят обектите, моделиращи обекти от реалния свят и взаимодействията между тях. Това позволява изграждането на софту­ерни сис­теми, които въпреки сложността си са разбираеми и в следствие на то­ва - лесни за разширяване и поддръжка. Даден обект, представящ същ­ност (entity) от ре­ал­ния свят, би могъл (почти) без изменения да играе ро­ля­та на същия фи­зи­чес­ки обект в друга софтуерна система.

Обектите притежават атрибути, които описват свойствата на им, и опе­­рации – възможните действия, които могат да се извършват с обекта.

Преизползване на програмния код

Едно от основните предимства на обектно-ориентирания подход е, че позволява лесно преизползва­не на програмния код (code reuse). Това се постига с помощта на наследяване и по­ли­мор­фи­зъм, които ни позволяват да дефинираме общите свойства и действия за множество от типове обек­ти само в един от тях.

Основни принципи на ООП

Трите основни принципа на ООП са капсулация на данните, наследяване и полиморфизъм. Те са основните характеристики, които определят един език за програмиране като обектно-ориентиран.

Капсулация на данните

Основна концепция в ООП е обектът да се разглежда като "черна кутия" – из­ползващите обекта "виждат" само атрибутите и операциите, които са присъщи на обекта от реалния свят, без да се интересуват от конкретната им реализация – клиентът на обекта трябва да знае само какво може да прави обектът, а не как го прави. В такъв смисъл "капсулация" означава скриване на ненужните детайли за обектите и откриване към външния свят само на важните техни характе­ристики и свойства.

Обектите в ООП съдържат своите данни и средствата за тяхната обра­ботката, капсулирани като едно цяло.

Наследяване

Ако един обект съдържа всички свойства и действия на друг, първият може да го наследи. По този начин наследеният обект освен собствените си атрибути и операции приема и тези на "родителя" си (базовия клас), като така се избягва повторното им дефиниране и се позволява съз­да­ването на йерархии от класове, моделиращи по естествен начин за­ви­симостите от реалността.

За да изясним това понятие, ще си послужим с класическият в OOП пример за класа от обекти Animal, който пред­ставлява абстракция за мно­жест­вото от всички животни. Всички обек­ти от този клас имат общи ха­рак­те­ристики (например цвят и възраст) и обща функционалност, например операциите Eat и Sleep, докато за класът Dog, представляващ мно­жест­во­то от всички ку­че­та, които също са животни, би могъл да предоставя опе­ра­циите Eat, Sleep и Bark. Удачно е кла­сът Dog да наследи Animal – тогава той ще съдържа описание само на соб­стве­ното си действие Bark, докато те­зи на Eat и Sleep ще получи от ба­зо­ви­я си клас.

Чрез наследяването се постига специализация, или конкретизация на кла­со­вете, тъй като базовият клас представлява категория от обекти по-обща от тази на наследяващите го. Ако си послужим с горния пример, мно­жест­вата на кучетата и котките са подмножества на множеството от всич­ки животни.

Може да се каже, че наследяването моделира "is-a" отношението между обек­­тите, например можем да твърдим, че кучето е животно, тъй като то "мо­­же да прави" всичко, което и животното и притежава всички животин­ски характеристики (цвят, възраст и т.н.).

Полиморфизъм

Полиморфизъм буквално означава приемането на различни форми от един обект. Нека е даден базов клас, представящ категория от обекти, които ре­ализират общо действие, което се наследява от множество класове, опис­­ващи по-тесни категории. Въпреки, че те всички споделят това дей­ствие, те могат да го реализират по различен начин. Когато раз­по­ла­га­ме с обек­ти от базовия клас, знаем че всички те реализират това дей­ствие, не­за­ви­си­мо на кой наследен клас принадлежат. Поради това можем да го из­пол­зваме без да се интересуваме от конкретната му реализация. На­при­мер, ако кла­сът Animal предоставя действието Talk и разгледаме нас­ле­дя­ва­щите го кла­сове Dog и Cat, всеки от тях го ре­а­ли­зи­ра по кон­кретен начин. И ако има­ме животно, което издава звук и то е ку­че – ще лае, а ако е котка – ще мяучи.

Полиморфизмът позволява унифицираното извършване на действие над различни обекти, които го реализират. В този случай издаването на звук от животно е по­ли­мор­фно действие – такова, което се реализира по раз­ли­чен начин в раз­лич­ни­те наследници на базовия клас.

Основни понятия в ООП

Без да претендираме за изчерпателност ще даден кратка дефиниция за основните понятия от ООП, които ще използваме по-нататък. Ако откри­вате, че повечето от тези термини са ви напълно непознати, ви препоръч­ваме първо да се запознаете с принципите на обектно-ориентираното програмиране от някоя специализирана книга по ООП, а след това да продължите нататък. В настоящата тема ще направим преглед на реализа­цията на ООП в .NET Framework, а не на ООП като идеология.

Клас

Класовете са категории от обекти, споделящи общи свойства и операции, които могат да се извършват върху тях. Например класът "студент" пред­ста­вя мно­жеството от всички студенти. Класът не съществува реално като фи­­­зи­­чес­ка същност, а по-скоро можем да го разгледаме като описание на не­­го­ви­те обекти.

Обект

Обект наричаме конкретен елемент от даден клас (инстанция), например студентът Тодор Георгиев, трети курс, ядрена физика в СУ.

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

Про­цесът на създаване на обект от даден клас е инстанциране. Обектите, съз­­дадени при инстанциране на даден клас, се наричат негови ин­стан­ции. Например в резултат от инстанцирането на класа "студент" можем да получим обекта "Иван Петров", който е инстанция на класа "студент".

Свойство

Свойство се нарича видима за външния свят характеристика (атрибут) на обектите от даден клас. Например свойства на класа "студент" са личните имената му, личните му данни, оценките му и др.

Метод

Метод е действие, което всички обекти от даден клас могат да извършват. Например всички обекти от класа "студент" могат да извършват действи­ето "явяване на изпит".

Интерфейс

Интерфейсът е описание на съвкупност от действия, които даден обект може да из­вър­шва. Ако един обект може да извършва всички действия от даден ин­тер­фейс, казваме че обек­тът реализира, или имплементира интер­фейса. Кла­сът "студент", на­пример, би могъл да реализира интер­фейса "учащ" съдържащ действието "учене".

Наследяване на класове

Наследяване в ООП наричаме възможността един клас, наричан нас­ледник, да при­добие свойства и действия на друг клас – родител (базов клас). Например класът "пре­къс­нал студент" би могъл да наследи класа "студент", като към наследените методи и свойства добави собствени, например "получаване на призовка от военните власти".

Абстракция на данните

Абстракция на данните наричаме възможността да работим с данни без да се интересуваме от тяхното вът­реш­но представяне, а само от операциите, които можем да извършваме над тях. Удачно е този подход да се осъще­стви чрез използването на ин­тер­фейси.

Структури от данни, които дефинират група от операции, но не разкриват информация как са имплементирани тези операции, се наричат абстракт­ни структури от данни.

Абстракция на действията

Абстракцията на действията е възможността да изпълняваме действия, без да се интересуваме от кон­крет­ната им реализация. Обикновено се постига чрез полиморфизъм. Например ако извикваме даден метод от даден клас през неговия базов клас или интерфейс, ние реално извикваме абстрактно действие от базовия клас, което е реализирано в класа-наследник.

ООП и .NET Framework

В .NET Framework обектно-ориентираният подход е залегнал на най-дъл­бо­ко архитектурно ниво. Всеки тип, дефиниран от потребителя, и всич­ки типове от Common Type System (CTS) насле­дяват System.Object или не­гов наследник.

В някои обектно-ориентирани езици се използват примитивни типове дан­ни (булеви, числови, символни), които в езиците от .NET Framework са съ­­що наследници на System.Object.

Всички .NET езици са обектно-ориентирани и приложенията се пишат изцяло обектно-ориентирано – няма глобални функции и всички действия се извършват или чрез създаване на обекти и с използване на методите и свой­ствата им, или чрез използване на статични членове (тях ще раз­гле­даме малко по-нататък).

Типове данни

В предходната глава въведохме понятието тип и разделихме типовете в C# на типове стойностни и референтни. Следва да представим една по-подробна класифи­кация на типовете данни в .NET Framework. Те биват:

-     класове

-     структури

-     интерфейси

-     делегати

-     изброени типове

Реализация на понятието клас

Понятието "клас" от ООП се реализира в .NET Framework чрез класове (classes) и структури (structs).

Не трябва да бъркаме понятието клас от концепциите на ООП с понятието клас в .NET Framework. Разликата е тънка – класът в .NET действително е клас според ООП терминологията, но обратното не е вярно. ООП терминът клас се реализира и по още един начин – чрез структури.

Основната разлика между класовете и структурите в .NET Framework е, че структурите са стойностни типове, докато класовете са референтни типо­ве. Структурите по-интуитивно моделират данни, от които се очаква пове­дение като на примитивни типове, докато класовете по-добре моделират обекти от реалния свят, които могат да извършват определени действия.

Тъй като типовете по стойност в общия случай се създават в стека за изпълнение на програмата, структурите е добре да съдържат малки по-обем данни, а по-големите количества е удачно да се обработват с помощта на класове, инстанциите на които съхраняват членовете си в динамичната памет.

Множествено наследяване

Някои обектно-ориентирани езици позволяват използването на мно­жест­ве­но наследяване – възможността един клас да приеме методи и свой­ства от няколко родителя. При проектирането на .NET Framework е взето ре­шение това да не се допуска.

Една от причините в .NET Framework да няма множествено наследяване е, че множественото нас­ледяване води до конфликти, например ако един клас наследи еле­мент с едно и също име от повече от един родител.

От друга страна мно­жест­веното наследяване води до по-сложни и трудно раз­би­ра­е­ми йерар­хии – такива, образуващи граф, докато при наследява­нето от единствен ро­дител се получава дърво.

В .NET Framework приемането на характерис­тики и поведение от повече от ед­на същности от реалния свят се осъ­щест­вя­ва чрез реализи­ране на ня­кол­ко интерфейса едновременно, при което обаче не може да се насле­дят данни или програмен код, а само дефиниции на действия.

Класове

Класовете в C# са основните единици, от които се състоят програмите. Те моделират обектите от реалния свят и могат да дефинират различни чле­нове (член-променливи, методи, свойства и др.). Нека видим как изглеж­да един примерен клас на езика C#:

class Student 

{

  // Private member declarations

  private string mFirstName;

  private string mLastName; 

  private string mStudentId;

 

  // Constant

  private const double PI = 3.1415926535897932384626433;

 

  // Constructor

  public Student(string aStudentId)

  {

       mStudentId = aStudentId;

  }

 

  // Property

  public string FirstName

  {             

     get

     {

       return mFirstName;

     }

     set

     {

       mFirstName = value;

     }

  }

 

  // Read-only property

  public string StudentId

  {             

     get

     {

       return mStudentId;

     }

  }

 

  // Method

  public string StoreExamResult(

     string aSubject, double aGrade)

  {             

     // ...

  }

}

В горния пример е дефиниран класът Student, илюстриращ някои от видовете членове, които класовете могат да реализират – капсулираните полета  mFirstName, mLastName и mStudentId, константата PI, кон­струк­то­рът Student(), свойствата FirstName и StudentId и методът StoreExamResult(). С течение на темата ще се запознаем по-отблизо с всеки от тези видове членове.

Членове на тип

В .NET типовете "клас" и "структура", като реализация на понятието клас от ООП, могат да съдържат в себе си членове (members), подобно на други обектно-ориентирани езици като Java и C++. Членовете могат да бъдат от един от следните видове:

-     полета, или член-променливи (fields)

-     константи (constants)

-     методи, или член-функции (methods)

-     свойства (properties)

-     индексатори (indexers)

-     събития (events)

-     оператори (operators)

-     конструктори (constructors)

-     деструктори (destructors)

-     вложени типове (класове, структури, изброени типове и др.)

Видимост на членовете

Множеството от типове, които могат да "виждат" определен член на даден клас се определя от видимостта. Правилното задаване на видимостта на членовете е ключов момент в разработването на йерархии от класове, тъй като основен принцип в ООП е клиентът на класа да вижда само това, което му е необходимо, и нищо повече. Следва описание на нивата на видимост в .NET Framework.

public

Глобална видимост – членовете с такова ниво на достъп могат да се достъпват от всеки тип.

protected internal

Това са членовете, видими от всички типове, дефинирани в асемблито, в което е дефиниран дадения, a също и от наследниците на типа.

internal

Членове, които се достъпват от всички типове, дефинирани в асемблито, в което е дефиниран дадения.

protected

Членове, видими само от наследниците на дадения тип.

private

Капсулирани членове, видими единствено в рамките на типа.

Член-променливи

Данните, с които инстанцията на класа работи, се съхраняват в член-про­мен­ливи (или още полета). Те се дефинират в тялото на класа и могат да се достъпват от други ви­дове членове – методи, конструктори, ин­дек­са­тори, свойства. В след­ва­щи­я пример ще покажем няколко декла­рации на член-про­мен­ли­ви, за които в последствие ще дадем обяснения.

class Student 

{

  private string mFirstName;

  private string mLastName; 

  private string mStudentId;

  private int mCourse = 1;

  private string mSpeciality;

  private Course[] mCoursesTaken;

 

  // Avoid missing the visibility modifier

  string mRemarks = "(няма забележки)";

}

Дефиниране на ниво на видимост

Дефиницията на всяко поле започва с ниво на видимост. Допустими са вси­чки по-горе изброени нива на видимост, но в примера са из­пол­зва­ни само private, защото скриването на полетата от из­пол­зва­щи­те класа, т.е. указването на видимост private или protected, е утвърдена практика в ООП. Когато искаме да предоставим данните на класа на окол­ния свят в .NET е прието вместо полета с ниво на достъп "public" да се из­ползват свойства, на които ще се спрем малко по-късно. Степента на видимост може и да не бъде определена явно, както е в последния ред за по­ле­то mRemarks от примера и в този случай се подразбира private. Тази прак­тика не се препоръчва, защото води до по-неясен код.

Дефиниране на тип

Следващият елемент от дефиницията на член-променлива е типът, който се указва задължително. Може да бъде произволен .NET тип от CTS или де­финиран от потребителя.

Задаване на име

След типа следва името на дефинираното поле, чрез което се обръщаме към него. То представлява идентификатор, т. е. последователност от unicode символи – главни и малки букви, цифри, -(тире) и _(подчерта­ващо тире), незапочваща с цифра или тире.

Имената на полетата и въобще на членовете в .NET Framework могат да бъдат идентични със съществуващи имена на типове или пространства от имена (на тях ще се спрем в края на темата). Например класът Student може да има свойство със същото име Student. Могат да бъдат и запазени думи, но само ако бъдат предшествани от @. Допуска се и използването на нелатински букви в имената, но не се препоръчва.

Задаване на стойност

При дефиницията на поле можем да му зададем стойност, както в примера това е направено за mCourse и mRemarks. Ако началната стойност бъде про­пусната, на член-променливата се задава стойност по под­раз­би­ране. За ре­фе­рен­тните типове това е null, а за стойностните типовете е 0 или неин еквивалент (например false за boolean). В .NET Framework всички членове и променливи се инициализират автоматично. Това намалява грешките, възникващи заради използването на неинициализирани про­мен­ливи.

Константни полета

Константните полета (или само константи) много приличат на обик­но­ве­ни­те полета, но имат някои особености. Нека обърнем внимание на след­ния при­мер, който показва няколко дефиниции на константи:

public class MathConstants 

{

  public const string PI_SYMBOL = "π";

  public const double PI = 3.1415926535897932385;

  public const double SQRT2 = 1.4142135623731;

}

От примера виждаме, че дефиницията на константа е дефиницията на поле с добавена ключовата дума const. Има и някои други разлики.

При декларирането на константно поле е задължително да се предостави стойност. Освен това стойността на константата не може да бъде про­ме­ня­на по време на работата с типа, в който е дефинирана – може само да бъ­де прочетена. Константите реално не съществуват като полета в типа, а съ­ществуват само в сорс кода и се заместват със стойността им по време на компилация. Поради тази причина const декларациите в C# се наричат още compile-time константи, т. е. константи, които съществуват само по време на компилацията.

Полета само за четене

Друг специален вид полета, подобни на константите, са полетата само за четене (read-only fields). Те се различават от константните по това, че стойността им освен при дефиницията може да бъде зададена и в кон­струк­тор, но от там нататък не може да бъде променяна. Член-променлива са­мо за четене се декларира, като се използва запазената дума readonly, като в примера:

class ReadOnlyDemo

{

  private readonly int mSize;

 

  public ReadOnlyDemo(int aSize)

  {

     mSize = aSize; // cannot be further modified!

  }

}

За разлика от константите, полетата само за четене са реални полета в типа, които обаче, задължително трябва да се инициализират в конструк­тора на класа или при деклариране, защото след това не може да им бъде присвоя­вана стой­ност и биха останали с подразбиращата се. Поради тази причина те се наричат още run-time константи, т. е. константи, които се инициализират по време на изпълнение на програмата.

Методи

Методите (или още член-функции) дефинират операции за типа, в който са дефинирани. Те могат да боравят с членовете му, независимо от сте­пен­та им на видимост, да ги достъпват и променят (освен полетата обя­ве­ни като константни или само за четене).

В C# функции могат да бъдат дефинирани единствено като членове на клас или структура, за разлика от други обектно-ориентирани езици, къ­де­то се използват глобални функции – такива, които не са обвързани с конкре­тен тип и са общодостъпни. В C# функции, които се достъпват без да е нужна инстанция на даден клас, се дефинират като статични. На тях ще се спрем след малко.

Задаване на видимост

Подобно на полетата, и методите могат да имат ниво на видимост. И син­тактично, и от гледна точка на стила на програмиране, на методите е допустимо да се зададе коя да е от възможните нива на видимост, тъй като те представляват действията с типа и за някои от тях е необходимо да бъдат видими за околния свят, а за други – не. Отново подразбиращото се ниво на видимост е private, но е препоръчително да се декларира изрично.

Параметри и върната стойност

Методите могат да приемат параметри и да връщат стойност. Параметрите имат тип, който може да бъде всеки валиден .NET тип. Върнатата стойност може да бъде също от всеки възможен тип, а може и да отсъства. Нека обърнем внимание на следния пример:

class MethodsDemo

{

  public void SayHiGeorgi()

  {

     SayHi("Гошо");

  }

 

  public void SayHiPeter()

  {

     SayHi("Пешо");

  }

 

  private void SayHi(string aName)

  {

     if (aName == null || aName == "" )

     {

        return;

     }

     Console.WriteLine("Здравей, {1}", aName);

  }

 

  public int Multiply(int x, int y)

  {

     return x * y;

  }

}

Първите два метода, SayHiGeorgi() и SayHiPeter(), не приемат никакви па­раметри и не връщат стойност. Третият, SayHi(string aName), приема един параметър от тип string и не връща стойност. Последният, Multiply(int x, int y), приема два параметъра от тип int и връща стой­ност също от тип int.

В дефинициите на първите три метода от примера забелязваме ключовата дума void – тя се използва при методи, които не връщат стойност. За методи, които връщат стойност, вместо ключовата дума void се указва типа на връщаната стойност.

В последния метод забелязваме как се употребява ключовата дума return за връщане на стойност. Същата ключова дума използваме и за прекратя­ване на изпълнението на метод, който не връща стойност, както в метода SayHi(aName).

Методи с еднакви имена

В C# е допустимо един тип да има два и повече метода с едно и също име, но с някои ограничения. Ще въведем понятие, свързано с из­пол­зва­не­то на едно и също име за няколко метода. Комбинацията от името, броя и типа на параметрите на метод наричаме сигнатура. Ако два метода имат едно и също име, те задължително трябва да се различават по сиг­на­ту­ра. След­ва­щият пример илюстрира дефинирането на три метода с еднакви име­на:

int Sum(int a, int b)

{

  return a + b;

}

 

int Sum(int a, int b, int c)

{

  return a + b + c;

}

 

long Sum(long a, long b, long c) // avoid this

{

  return a + b + c;

}

Горните дефиниции са напълно валидни – първите два метода се раз­ли­ча­ват по броя на параметрите си, а вторият и третият – по типа.

Трябва да сме особено внимателни с дефиниции като последните две и е препоръчително да се избягват, тъй като не е очевидно кой метод ще бъде извикан при обръщение като int sumTest = sum(1,2,3). Компилаторът по никакъв начин не ни предупреждава за двусмислието. В горния пример ще бъде извикан първият метод – sum(int a, int b, int c).

Статични членове

Както вече споменахме, в C# функции, които могат да се извикват без да е нужна инстанция на клас, се реализират като статични (или общи) методи. Това става, като в дефиницията им включим ключовата дума static. Статичните членове се споделят от всички инстанции и се изпол­зват за пресъздаване на свойства и действия, които са постоянни за всич­ки обекти от дадения клас. Достъпът до статичните членове на типа се извърша директно, а не през инстанция, както в следващия пример:

class Bulgaria

{

  private static int mNumberOfCities = 267;

 

  public static int NumberOfCities

  {

     get

     {

       return mNumberOfCities;

     }

  }

 

  public static void AddCity(string aCityName)

  {

     mNumberOfCities++;

     // ...

  }

 

  // ...

 

  static void Main()

  {

     Console.WriteLine(

       "В България има {0} града.", Bulgaria.NumberOfCities);

  }

}

В примера видяхме дефинирането и използването на статични полета, методи и свойства. Използвахме статичните свойства без да инстанцираме класа Bulgaria никъде.

Важна особеност, която трябва да имаме предвид при използването на статични методи и свойства, е че те могат да използват само статични полета. Полетата, които са обвър­зани с инстанция могат да се достъпват само в ней­ния контекст, а статичните методи и свойства са незави­сими от инстанцията.

Статичните полета на типа много приличат на глобалните променливи в по-старите езици за програмиране като C, C++ и Pascal. Както глобалните променливи, статичните полета са достъпни от цялото приложение и имат само една инстанция.

От членовете на типа, освен полетата, свойствата и методите също и конструкторите, индексаторите и събитията могат да бъдат статични. Кон­стантите също са общи за всички инстанции на типа, но не могат да бъдат статични. Деструкторите също не могат да бъдат статични, докато опера­торите задължително са.

Конструктори

Конструкторите се използват при създаване на обекти и служат за инициализация, или начално установяване на състоянието на полетата на обекта. Механизмът на работа и синтаксисът за дефиниране на кон­струк­то­рите в C# са подобни на други обектно-ориентирани езици, като Java и C++ с някои особености, на които ще обърнем внимание. Допуска се използването на повече от един конструктор, като кон­структорите трябва да се раз­личават по броя и/или типа на параметрите. Възможно е и да не се де­фи­нира конструктор и в такъв случай компила­торът създава подразбиращ се – публичен, с празно тяло и без параметри.

Инициализиране на полетата

Съществуват три възможности за инициализацията на полетата на обекта – да бъдат инициализират в конструктор, при декларацията им или да нямат изрично зададена стойност.

Инициализациите, описани в тялото на конструктора се изпълняват по време на изпълнението този конструктор – при създаване на обект от съответния клас с ключовата дума new в C#.

Инициализациите, дефинирани при декларацията на полетата се из­пъл­ня-ват директно преди конструктора. Можем да приемем, че при ком­пи­ла­ци­я­та инициализациите на полетата се добавят в началото на всеки кон­струк­тор. Всъщност C# компилаторът прави точно това скрито от програмиста – поставя код, който инициализира всички член-променливи на типа във всички негови конструктори.

Полетата, които нямат зададена начална стойност, получават стойност по под­разбиране (нулева стойност). Това поведение се изисква от специ­фикацията на езика C# и не зависи от конкретната имплементация на компилатора.

Конструктори – пример

Със следващия пример ще разгледаме примерни дефиниции на кон­струк­то­ри на базов клас с един наследник:

class Student 

{

  private string mName;

  private int mStudentId;

  private string mPosition = "Student";

 

  public Student(string aName, int aStudentId)

  {

     mName = aName;

     mStudentId = aStudentId;    

  }

 

  public Student(string aName) : this(aName, -1)

  {

  }

 

  public static void Main()

  {

     Student s = new Student("Бай Киро", 12345);

  }

}

 

public class Kiro : Student

{

  public Kiro() : base("Бай Киро", 12345)

  {

  }

 

  // ...

}

Забелязваме употребата на ключовите думи this и base след де­фи­ни­ци­я­та на конструкторите на класа. Те представляват съответно обръщения към друг конструктор на същия клас и към конструктор на базовия клас, като в скобите се изреждат параметрите, които се подават на извиквания конструктор. В примера е използване наследяване, на което ще с спрем в детайли след малко (класът Kiro наследява класа Student).

Изследване на MSIL кода за конструкторите в C#

В следващата демонстрация ще си послужим с инструмента IL DASM (ildasm.exe), който е част от .NET Framework SDK, за да разгледаме MSIL кода, който C# компилаторът ге­нерира за класа Student, който дефини­рахме в примера по-горе. С това упражнение не само ще се запознаем с работата с инструмента, но и ще забележим особеностите в генерирания код, свързани с полетата със зададена стойност при декларацията. Ето стъпки­те, които трябва да на­пра­вим:

1.  Отваряме Demo-1-Constructors.sln, елементарен Visual Studio .NET проект с единствен C# файл, който съдържа кода от горния пример. Компилираме проекта.

2.  Стартираме командния интерпретатор към Visual Studio .NET. Не използваме стан­дартния cmd.exe, а този, който се намира в Start -> Programs -> Microsoft Visual Studio 2003 -> Visual Studio Tools, защото той се стартира с регистрирани пътища към .NET ин­стру­ментите, които се използват от командния ред.

3.  Избираме директорията, където се намира изпълнимият файл, получен при компилиране на проекта – Demo-1-Constructors.exe. Ако не сме променили настройките на Visual Studio .NET, това ще е директорията <директория на проекта>\bin\Debug.

4.  Извикваме от командния ред инструмента ildasm и му подаваме като параметър компилираното приложение:

ildasm Demo-1-Constructors.exe

Ето как изглежда прозорецът на инструмента, в който е заредено асемблито от приложението, когато разпънем всички елементи от дър­вото:

IL DASM показва дърво за асемблито, в което различаваме класа Student и членовете му. Ако се придвижим по дървото до конструк­торите на класа, можем да изследваме техния IL код, както е показано на след­ващата картинка:

В кода, генериран за конструктора с един параметър, се вижда обръ­ще­нието към този с два параметъра. Ако повторим същото действие и с втория конструктор, можем да наблюдаваме и неговия IL код (на картинката по-долу).

Забелязваме, че задаването на стойност на полетата с инициа­лизация при декларацията реално се извършва в началото на втория конструк­тор. Реално тези полета се инициализират и от първия конструктор, защото той извиква втория.

Singleton клас

В този пример ще представим един популярен шаблон в обектно-ориенти­рания дизайн – клас, който може да има най-много една инста­нция в рам­ки­те на цялото приложение. Такъв клас наричаме singleton. За ре­а­ли­зи­ра­нето на такива класове се използва следният подход:

public sealed class Singleton

{

  private static Singleton mInstance = null;

 

  private Singleton()

  {   

  }

 

  public static Singleton Instance

  {

     get

     {

       if (mInstance == null)

       {

          mInstance = new Singleton();

       }

       return mInstance;

     }

  }

}

Целта на задаването на private видимост за конструктора на класа е за да не могат да се създават инстанции освен от членове на класа, както в случая статичното свойство Instance. В дефиницията на класа е из­пол­зва­на ключовата дума sealed, която указва, че класът не може да бъде наследяван.

Горният пример само демонстрира използването на sealed класове и час­тен конструктор. В реална ситуация при реализацията на singleton шаб­лона трябва да се вземе предвид, че е възможно няколко нишки (threads) едновременно да се опитат да извлекат инстанцията на singleton класа и да се получи нежелано поведение. Затова обикновено реализацията на този шаблон изисква допълнителни усилия за нишково обезопасяване на работата на класа. На работата с нишки ще обърнем специално внимание в темата "Многонишково програмиране и синхронизация".

Статичен конструктор

Конструкторите, подобно на други видове членове на класа, могат да бъдат обявени за статични, с тази особеност че статичният конструктор може да бъде най-много един и не може да приема параметри и модифи­катори за достъп.

Извикване на статичен конструктор

Статичният конструктор се използва за инициализация на статичните членове и се извиква автоматично. Извикването на статичният кон­струк­тор се извършва "зад кулисите" от CLR. Това става по време на изпълне­нието на про­гра­мата и мо­мен­тът на стартирането му не е точно опре­делен. Това, което е сигурно, е че статичният конструктор е вече извикан когато се създаде първата инстанция на кла­са или когато се достъпи някой негов статичен член. В рамките на програмата, ста­тич­ният кон­структор може да бъде извикан най-много веднъж.

Статичен конструктор – пример

В следващия пример ще разгледаме класа SqrtPrecalculated, който из­ползва ста­тичен конструктор:

class SqrtPrecalculated

{

  public const int MAX_VALUE = 10000;

  private static int[] mSqrtValues; // static field

 

  // Static constructor

  static SqrtPrecalculated()

  {

     mSqrtValues = new int[MAX_VALUE + 1];

     for (int i = 0; i <= MAX_VALUE; i++)

       mSqrtValues[i] = (int) Math.Sqrt(i);

  }

 

  // Static method

  public static int GetSqrt(int aValue)

  {

     return mSqrtValues[aValue];

  }

 

  static void Main()

  {

     Console.WriteLine(GetSqrt(1000));

  }

}

Класът SqrtPrecalculated служи за бързо изчисляване на корен квад­ратен. Той предоставя статичния метод SqrtPrecalculated(), който връ­ща цялата част на квадратния корен на ар­гу­мен­та си.

За по-голямо бър­зо­дей­ствие всички квадратни корени на числата от 0 до 10000 се из­чис­ля­ват предварително в статичния конструктор и после се използват наготово. Мно­жеството от стойностите се съхранява в статич­ното по­ле mSqrtValues[], което се инициализира в статичния конструк­тор, който се изпълнява преди първия опит за достъп до класа.

Ще илю­стрираме поведението на статичните конструктори в .NET Framework, ка­то с помощта на дебъгера на VS.NET наблюдаваме как преди да започне да бъде използван даден клас се изпълнява първо статичният му кон­струк­тор.

Проследяване на изпълнението на примера

Ще използваме дебъгера на Visual Studio .NET за да проследим из­пъл­не­нието на кода от горния пример, който се съдържа в приложението Demo-2-TestStaticConstructor от демон­стра­циите­. Ще изпълним последова­телно следни­те стъп­ки:

  1. Отваряме с VS.NET TestStaticConstructor.sln и го ком­пи­лираме.
  2. Слагаме точки на прекъсване (breakpoints) на първия ред на ста­тич­ния конструктор (static SqrtPrecalculated()) и във фун­к­ци­я­та Main() като щракаме с мишката на равнището на тези редове в празното поле от ляво на областта за редактиране на код. След като поставим точките на прекъсване средата изглежда по следния начин:

  1. Стартираме програмата в дебъг режим (от меню Debug -> Start или с [F5]) и проследяваме как дебъгерът на Visual Studio .NET спира първо в статичния конструктор, а след като му зададем да продължи, спира в метода Main(). Това илюстрира как функцио­налността от статичния конструктор се изпълнява преди първото използване на класа. Ето как изглежда средата в момента, в който програмата е спряла в статичния конструктор:

Свойства

Свойствата са членове на класовете, структурите и интерфейсите, които обикновено се изпол­зват за да контролират достъпа до полетата на типа.

Свойствата приличат на член-променливите по това, че имат име, по-което се достъпват, и стойност от някакъв предварително определен тип. От гледна точка на синтаксиса за достъп до тях, свойствата изглеждат по същият начин както полетата. Разликата се състои в това, че свойства съдържат код, който се изпълнява при обръщение към тях, т. е. извър­шват действия. Свойствата могат да бъдат и ста­тич­ни.

Прочитане и присвояване на стойност

Свойствата могат да имат два компонента (accessors):

-          код за прочитане на стойността (get accessor)

-          код за присвояване на стойността (set accessor)

Когато създаваме свойства можем да предоставим дефиниции на двата компонента, както и на само един от тях, но задължително трябва да е дефиниран поне единият. Според предоставените компоненти делим свой­ствата на три вида:

-          Свойства само за чете (read only) - такива, които дефинират само код за прочитане на стойността им.

-          Свойства за четене и писане (read and write) - когато имат и двата компонента.

-          Свойства само за писане (write only) - когато е предоставен само код за присвояване на стойност.

Пример за свойства

Ще дефинираме класа Person за да илюстрираме дефинирането и из­пол­зва­нето на свойства:

public class Person

{

  private string mName;

  private DateTime mDateOfBirth;

 

  // Property Name of type string

  public string Name

  {

     get

     {

       return mName;

     }

     set

     {

       if ((value != null) && (value.Length > 0))

       {

          mName = value;

       }

       else

       {

          throw new ArgumentException("Invalid name!");

       }

     }

  }

 

  // Property DateOfBirth of type DateTime

  public DateTime DateOfBirth

  {

     get

     {

       return mDateOfBirth;

     }

     set

     {

       if ((value.Year >= 1900) &&

          (value.Year <= DateTime.Now.Year))

       {

          mDateOfBirth = value;

       }

       else

       {

          throw new ArgumentOutOfRangeException(

            "Invalid date of birth!");

       }

     }

  }            

 

  // Read-only property Age of type int

  public int Age

  {

     get

     {

       DateTime now = DateTime.Now;

       int yearsOld = now.Year - mDateOfBirth.Year;

       DateTime birthdayThisYear =

          new DateTime(now.Year, mDateOfBirth.Month,

          mDateOfBirth.Day, mDateOfBirth.Hour,

          mDateOfBirth.Minute, mDateOfBirth.Second);

       if (DateTime.Compare(now, birthdayThisYear) < 0)

       {

          yearsOld--;

       }

       return yearsOld;

     }

  }

}

 

// Property usage example

class PropertiesDemo

{

  static void Main()

  {

     Person person = new Person();

     person.Name = "Svetlin Nakov";

     person.DateOfBirth = new DateTime(1980, 6, 14);

     Console.WriteLine("{0} is born on {1:dd.MM.yyyy}.",

       person.Name, person.DateOfBirth);

     Console.WriteLine("{0} is {1} years old.",

       person.Name, person.Age);

  }

}

В примерния клас виждаме дефинициите на две свойства за четене и писане - Name от тип string и DateOfBirth от тип DateTime, както и едно само за четене – Age от тип int.

Можем да доловим различните аспекти на употребата на свойства - едно свойство може да бъде просто обвивка около поле на типа, но може и да реализира по-сложна логика. Например свойствата Name и DateOfBirth в примера просто връщат стойността на полетата, които обвиват, или я задават след съответните проверки за валидност. Свойство може да бъде и абстракция на данни, извличането и съхранението на които би могло да бъде свързано със сложна обработка. Опростен пример за това е Age, което връща стойност, резултат от извършване на изчисления, в случая разликата между те­ку­щата дата и рождената дата на лицето.

Проследяване на изпълнението на свойствата

Ще си изясним работата със свойства като проследим хода на програмата по време на достъпа до тях. За целта ще си послужим с кода от примера, който се съдържа в приложението Demo-4-Properties от демонстрациите. Той съдържа горния пример. Нека изпълним следните стъпки:

  1. Отваряме с VS.NET Demo-4-Properties.sln и го ком­пи­лираме.
  2. Стартираме програмата в режим на проследяване с [F11]. Програ­мата спира изпълнението си на първия ред, но без той да е изпълнен, ето така:

  1. Натискаме отново [F11] при което се създава обекта person и мар­ке­рът спира на следващия ред.
  2. Когато още веднъж натиснем [F11], забелязваме, че кодът, който след­ва да бъде изпълнен, е тялото на компонента за достъп до свойството Name на класа Person:

Това ни показва, че зад операцията "присвояване на стойност" на свойството стои кодът му за присвояване.

  1. С [Shift-F11] продължаваме изпълнението на програмата до на­пус­ка­нето на текущият блок – то спира отново на следващия ред в тя­ло­то на метода Main().
  2. С [F10] продължаваме изпълнението на програмата с още една стъпка. Резултатът е същият, както при натискането на [F11] с тази разлика, че не се изпълняват стъпка по стъпка вложените блокове. Така преминаваме през изпълнението на кода за присвоя­ване на стойност на свойството DateOfBirth на "един дъх" и мар­керът се позиционира на операцията Console.WriteLine("{0} is born on {1:dd.MM.yyyy}.", person.Name, person.DateOfBirth).
  3. Ако в този момент натиснем [F11] ставаме свидетели на изпълне­ние­то и на кода за достъп на свойството Name:

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

  1. С [F5] продължаваме изпълнението на програмата до края и виждаме резултата от изпълнението и:

В режим на дебъгване прозорецът, в който се изпъл­нява приложението, се затваря веднага след прик­лючване на изпълнението на кода и резултатът трудно може да бъде видян. Ако искаме да видим отпеча­тания резултат, трябва или да сложим точка на пре­късване преди края на Main() метода, или да се прид­вижим до последната операция стъпка по стъпка или да изпълним програмата не с [F5], а с [Ctrl-F5].

  1. Нека изследваме с IL DASM генерирания междинен код за пример­ното приложение, за да си изясним вътрешното представяне на свойствата.

Като стартираме ildasm и разгледаме с него IL кода за класа Person, забелязваме нещо много интересно – в класа Person има методи с префикс set_, отговарящи на компонен­тите за прис­вояване на дефинираните от нас свойства, и методи с префикс get_, които съответстват на компонентите за връщане на стойност.

На практика след компилация get и set частите на свойствата са се превърнали в методи, а достъпът до тях се е превърнал в операции за извикване на метод. Това е начинът, по който C# компилаторът компилира свойствата – превръща ги в методи, а достъпът до тях превръща в извиквания на методи.

Ето как изглежда класът Person в инструмента IL DASM:

Индексатори

Индексаторите в C# (indexers) са членове на класовете, структурите и интерфейсите, които предоставят индексиран достъп до данни на типа, подобно на достъпа до елементите на масив.

Индексаторите по синтаксис и семантика много приличат на свойства, но получават като параметър индекс на елемент, с който да работят. На практика, те представляват свойства, приемащи параметър и дори в някои .NET езици, например VB.NET, синтаксисът на декларирането им е същият като при свойствата.

Индексатори – пример

За да си изясним най-лесно как се дефинират индексатори, да разгледаме следния пример:

private object[] mElements;

 

public object this[int index]

{

  get

  {

     return mElements[index];

  }

}

Виждаме, че дефиницията на индексатор прилича на тази на свойство, но има и някои разлики. На индексатора не се задава име, а вместо него се задава запазената дума this.

Достъпът до индексатор на обект се извършва посредством името на променливата от типа, дефиниращ индексатора, последвана от индекса в квад­ратни скоби, също както се извършва достъпа до елемент на масив, например myArrayList[5].

Позовавайки се на начина, по който се обръщаме към индексаторите, можем да ги разглеждаме като средство за предефиниране на оператора []. Използването на индексатори позволява интуитивен достъп до обекти, които се състоят от множество компоненти, каквито са масивите и ко­лек­ци­ите.

Имитация на масив чрез индексатори – пример

За да илюстрираме по-пълно дефинирането и използването на индекса­тори, ще използваме след­ващия пример. Ще дефинираме клас, който ими­тира поведе­нието на масив от 32 стойности, всяка от които е или 0 или 1:

struct BitArray32

{

  private uint mValue;

 

  // Indexer declaration

  public int this [int index]

  {

     get

     {

       if (index >= 0 && index <= 31)

       {

          // Check the bit at position index

          if ((mValue & (1 << index)) == 0)

            return 0;

          else

            return 1;

       }

       else

       {

          throw new ApplicationException(String.

            Format("Index {0} is invalid!", index));

       }

     }

     set

     {

       if (index < 0 || index > 31)

          throw new ApplicationException(

            String.Format("Index {0} is invalid!", index));

 

       if (value < 0 || value > 1)

          throw new ApplicationException(

            String.Format("Value {0} is invalid!", value));

 

       // Clear the bit at position index

       mValue &= ~((uint)(1 << index));

 

       // Set the bit at position index to value

       mValue |= (uint)(value << index);

     }

  }

}

 

class IndexerTest

{

  static void Main()

  {

     BitArray32 arr = new BitArray32();

 

     arr[0] = 1;

     arr[5] = 1;

     arr[5] = 0;

     arr[25] = 1;

     arr[31] = 1;

 

     for (int i=0; i<=31; i++)

     {

       Console.WriteLine("arr[{0}] = {1}", i, arr[i]);

     }

  }

}

Класът BitArray32 представлява масив от битове с 32 елемента, който вътрешно съхранява стойностите им в едно 32-битово поле. Елементите му достъпваме посредством дефини­рания индексатор по същия начин, по който достъпваме елементите на вградените в CTS масиви. На масивите в .NET Framework ще се спрем в темата "Масиви и колекции".

Виждаме компонентите за прочитане и присвояване на стойността, които извършват проверка дали индексът е в съответния диапазон, след което чрез битови операции осъществяват достъп до посочения като параметър бит. При невалидни параметри се предизвиква изключение, чрез което се уведомява извикващия код за проблема. На изключенията ще се спрем подробно в темата "Управление на изключенията в .NET".

Проследяване на работата на индексатор

За да проследим работата на индексатора ще си послужим с приложе­ни­е­то от демонстрациите Demo-5-Indexers.sln, което съдържа кода от горния при­ме­р. Ще изпълним следните стъпки:

  1. Отваряме приложението и го компилираме.
  2. С [F11] стартираме изпълнение в режим на проследяване и маркерът се позиционира на първия ред от тялото на метода Main():

  1. Със следващото натискане на [F11] инициализираме обекта arr с подразбиращия се конструктор и текущ ред става присвояването arr[0] = 1.
  2. Когато продължим проследяването, виждаме как следващият код, който се изпълнява, е компонента за присвояване на стойност на индексатора:

  1. С [Shift-F11] прескачаме останалата част от блока и преминаваме с [F10] през другите присвоявания докато достигнем до цикъла, който про­чита стойностите от масива:

  1. В този момент при натискане на [F11] се изпълнява кодът за про­чи­та­не на стойността от масива. Забелязваме, че механизмът на из­пъл­нение на индексаторите е същият, както на свойствата.

  1. С помощта на инструмента IL DASM можем да си обясним при­ли­ки­те между свойства и индексатори. Когато разгледаме генерирания за приложението MSIL код виждаме, че индексаторите, както свой­ства­та, се реализират от двойка методи с имена get_Item и set_Item:

Индексатори с няколко параметъра

В .NET Framework се допуска дефинирането на индексатори, приемащи повече от един параметър. Примерно обръщение към такъв индексатор е конструкцията personInfo["Бай Иван", 68]. Възможно е в един тип да се дефинират и ня­колко индексатора с различен набор от параметри. Индек­са­торите не могат да бъдат статични, тъй като реализират индексиране в рамките на дадена инстанция.

Ето още един пример за индексатор, който приема два параметъра от тип символен низ и връща целочислена стойност:

class DistanceCalculator

{

  public int this[string aTown1, string aTown2]

  {

     get

     {

       if (aTown1.Equals("София") && aTown2.Equals("Варна"))

          return 470;

       else

          throw new ApplicationException("Unknown distance!");

     }