Самовчитель 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 – пропускає поточну ітерацію та переходить до наступної