Самовчитель C# для початківців
Я ж це вже робив, але хрін тепер знайдеш той шматок коду, гуглимо знову… Де знайти простий і зрозумілий посібник для початківця, а не тонкощі для мега-гуру?
Свіжі записи
- Uladzimir до запису C#, Interop.Word - помилка "Відсутня доступом до окремих рядків, оскільки таблиця має осередки, об'єднані по вертикалі."
- JosephLak до запису Як додати рядок/текст на початок файлу в C# і .Net
- Tomas до запису Розділювач тисяч та дробової частини для decimal
- fer до запису Працюємо з MS Word із C#, частина 1. Відкриваємо шаблон, шукаємо текст усередині документа
- Сергій до запису Самовчитель C# для початківців. 02. Функції, класи, об'єкти, колекції
Самовчитель C# для початківців. 02. Функції, класи, об'єкти, колекції
2.1 Функції.
Повернемося до старої задачі – виведення даних про людей. У нас є різні люди з даними у вигляді окремих прізвищ, імені, по-батькові, які треба вивести на екран - виду Пушкін Олександр Сергійович та Пушкін А.С. Щоб задача була правдоподібною, можна імітувати введення даних користувачем або завантаження із зовнішнього джерела, але все це буде марнуванням часу - реальні програми все одно працюють з графічним та/або веб-інтерфейсом. Просто тримаємо на увазі що в реальності людей не дві, а дві тисячі і заздалегідь їхні імена не відомі.
Отримуємо потворний код
Два рази повторюється той самий шматок коду - склеювання трьох рядків на одну. Два рази повторюється інший шматок коду - склеювання прізвища, перших букв імені та по батькові, точок. Логічніше винести шматки коду, що повторюються, в окреме місце, дати ім'я і в усіх інших місцях програми викликати їх з цьогоімені. Іншими словами зробити функції - шматки коду з власним ім'ям, які приймають на вхід якісь дані, щось з ними роблять і повертають назад якісь дані (хоча можливий варіант, коли вони нічого не приймають і не повертають, просто щось роблять).
Слова public static відкладемо на пару хвилин убік, string означає, що функція поверне назад рядок, CreateFio(string surname, string name, string otchestvo) - назва функції та опис того, що вона приймає на вхід три рядки.
Якби функція нічого не приймала і нічого не повертала, її опис виглядав би так
Код функції обрамляється фігурними дужками, значення повертається за допомогою ключового слова return
Весь код тестової програми з функціями
2.2 Класи та об'єкти
Код виглядає менш потворно, але зі змінними surname, surname2 явно щось не так. Особливо якщо людей побільшає. Непогано б зібрати всі дані, які стосуються однієї людини, у купку. І одразу додати до них ті функції, які не потрібні інші дані.
По суті нам треба перейти від типу даних "рядок" до нового типу даних "людина", в яку на даний момент будуть входити три рядки - прізвище ім'я та по батькові. Само собою для цього давно придумані спеціальні інструменти.
Сферичний чоловік у вакуумі, що має лише три рядки прізвища, імені та по батькові - цеклас. Клас ще можна порівняти з кресленням якогось об'єкта, наприклад ящика, який матиме розміри з трьох чисел – висоти, ширини та глибини.
А ось кожна конкретна людина зі своїми значеннями ПІБ буде примірником класу чоловік. Так само як кожна скринька зі своїми значеннями висоти, ширини та глибини буде екземпляром класу скриньки.Само собою у кожного класу може бути маса інших параметрів - наприклад і у людини і у ящика може бути параметр маса, у людини може бути параметр підлога - чоловіча або жіноча, а ось у ящика підлогу навряд чи буде (хоча хто знає, що нам готує непередбачуване майбутнє)
Ще раз наведу весь текст програми (файл Program.cs), щоб ви звернули увагу, де саме знаходиться опис класу.
У професійному програмуванні вважається поганим тоном давати вільний і безконтрольний доступ до даних, що зберігаються в класі. Щоб заборонити доступ ззовні до властивості Surname йому треба прописати інший модифікатор доступу, замість public - private. Записувати і зчитувати дані треба буде через спеціальні функції, аналогічні до тих функцій, які насправді щось обчислюють на кшталт GetFio. Щоб не возитися з написанням купи функцій типу GetName і SetName в C# застосовується спеціальний механізм властивостей, виходячи з яких вже за компіляції програми автоматично генеруються ці однотипні функції. Такий спосіб полегшити життя програмісту називається синтаксичним цукром. Visual Studio є навіть спеціальна функція для цього.

У цьому ж меню є багато інших вкрай корисних пунктів - наприклад, перейменування змінної, класу, простору імен або функції відразу у всіх місцях проекту.
Зверніть увагу, наскільки простіше став код, у якому створюються та виводяться на екран люди.
У тестовому прикладі може здатися, що таке спрощення не варте всієї мороки зі створенням класу і насправді є ускладненням, але таке враження створюється тільки через неприродну простоту тестового прикладу, реальні програми набагато складніші.
2.3 Структура програм реального світу. Простір імен.
Реальне програмування на 99% складається з використання вже готових класів та функцій, написаних іншими програмістами чи написання власних. Так як насправді ми маємо справу з сотнями і тисячами складних класів, що складаються з сотень властивостей і методів, то навіть класи доводиться розбивати на групи - простори імен.
Для нашої тестової програми ми використовуємо простір імен TestConsoleApplication, що складається з двох класів - Program і Person.
Клас Program автоматично створюється для кожного Net програми, це стандартний клас. Як правило, він складається з однієї функції/методу static void Main(string[] args), яка виконується при запуску програми.
Розробники C# та .Net дуже люблять класи. Просто дуже-дуже. Тож у результаті тут усе є класами і навіть функції без класів немає. Якщо вам не потрібні ні класи ні екземпляри, і ви хочете просто зробити кілька функцій - вам все одно доведеться створити клас, до якого додати кілька статичних (які не вимагають створення екземпляра) функцій.
Класичним прикладом такої функції може послужити множення
Яке десь в іншому місці викликається як
Але насправді в .Net вже є такий клас зі збіркою арифметичних функцій Math - до якого входять функції обчислення всіляких синусів, тангенсів, квадратних коренів, округлення чисел.
Інший приклад класу який по суті є бібліотекою функцій - клас Convert, що містить функції для перетворення одних типів даних в інші
У .Net Framework входить безліч вже готових класів від програмістів Microsoft, розділених на безліч просторів імен. Найбільш базові входять у простір імен System.
У цьому випадку ми викликаємофункцію public static void WriteLine(string value) із класу Console входить у простір імен System. І вже десь там усередині неї, швидше за все, ще кількома рівнями нижче виконується малювання по пікселях вікна з консоллю і наших букв.
Щоб не писати щоразу простір імен використовується директива using
і насправді, якщо ми вже прописали
У C# класами та об'єктами є все, у тому числі рядки. Кожен рядок – це насправді екземпляр класу String. Тепер можна зрозуміти і наступний код:
Тут ми викликаємо один з методів класу String - public string Substring(int startIndex, int length), який повертає шматок рядка і приймає два аргументи, індекс символу, з якого треба почати вирізування підрядка (нумерація починається з 0) і довжину підрядки, що вирізається.
Якщо нам не потрібні методи взагалі, просто хочеться зібрати в купку дані - можна використовувати структури. З іншого боку можна створити спеціальний клас без функцій, з одними даними - цього є розумна назва об'єкт передачі даних (Data Transfer Object, DTO).
2.4 Особливості зберігання даних у пам'яті. Посилальні та прості типи даних. Область видимості змінних.
Але основи треба знати всім – зараз зрозумієте чому. Для будь-яких даних потрібне місце у пам'яті комп'ютера. У деяких мовах на кшталт C і C++ програмістам треба вручну виділяти при створенні змінних і звільняти після завершення їх використання, зіштовхуючись з помилками на кшталт витоків пам'яті.
У C# справи інакше. Для найпростіших типів даних пам'ять комп'ютера виділяється автоматично, написавши int counter; ми автоматично отримаємо місце в пам'яті, яке буде за промовчанням записано 0.
З іншого боку, щоб реально скопіюватидані з одного об'єкта посилання типу в інший (і в результаті отримати два різні об'єкти з однаковими даними, а не два посилання на один і той же) доведеться писати спеціальний код.
Коли саме якийсь об'єкт стає непотрібним і потрапляє до уваги збирача сміття? Насправді особливості роботи збирача сміття відносяться до досить просунутих та глибоких питань, оскільки це дуже розумна машина. Але щонайменше одне пов'язане з цим поняття треба знати будь-якому програмісту - область видимості змінних. У більшості випадків ми втратимо контроль над змінною після того, як вона вийде з цієї області видимості - після цього вона більше не буде доступна програмісту і рано чи пізно її пам'ять буде звільнено збирачем сміття. Найчастіше область видимості змінної обмежується блоком коду, обмеженим двома фігурними дужками. Якщо всередині такого блоку є ще один блок, то на нього поширюється область видимості батьківського блоку. Приклад сферичної області видимості у вакуумі
А ось так усе буде гаразд.
Інший варіант першої помилки
А ось так все буде в порядку, оскільки змінні з одним і тим же ім'ям оголошується в різних областях видимості одного й того ж рівня, що не залежать один від одного
Само собою в реальному програмуванні порожні блоки фігурних дужок не застосовуються, але все вищесказане правильно для всіх тих випадків, коли вони використовуються осмислено - логічних умов, циклів, функцій.
Наочний приклад складнішого завдання, при вирішенні якого необхідно пам'ятати про особливості роботи збирача сміття - використання Word для виведення даних у звіти. У цьому випадку ми використовуємо ресурс, непідвладний збирачеві сміття - програму Word, що запускається та керується знашого коду. Якщо вона стає непотрібною, то її треба закривати вручну з коду - інакше на комп'ютері почнуть розмножуватися невидимі Word'и в необмежених кількостях.
2.5 Масиви, колекції та цикл foreach
Напевно, ви вже помітили щось дивне у всіх цих прикладах - їх неможливо використовувати для роботи з великими обсягами даних. Як зберігати інформацію про тисячі людей або точок на екрані? Два базові інструменти - масиви та колекції різних типів, найпростішим і найпоширенішим з яких є списки. Як нескладно здогадатися і те й те є класами, і те й те є набором значень, до яких можна звертатися за номером-індексом, що починається з нуля.
У чому відмінність масивів від списків? Подробиці відносяться до просунутих знань, але в цілому під масив місце в пам'яті виділяється відразу і якщо треба змінити його розмір, місце доводиться виділяти заново. Під список фіксований обсяг не виділяється, він змінюється динамічно, але операції над елементами виконуються повільніше. Таким чином, масив швидше і краще працює, якщо кількість елементів не змінюється, список - якщо змінюється. Але здебільшого ця різниця у швидкості не помітна і натомість інших чинників. Просунуті програмісти добре розуміють різницю між ArrayList, Dictionary, HashSet, LinkedList, Collection та іншими типами колекцій.
Обходити всі елементи у якомусь безлічі доводиться настільки часто, що у більшості сучасних мов при цьому зробили особливий цикл, в C# це цикл foreach, " кожного " .
Вийти з циклу можна за допомогою ключових слів break – просто припиняється виконання циклу та continue – пропускає поточну ітерацію та переходить до наступної