Опорний конспект для учнів.

Тема 4 "Основи обєктно-орієнтованого програмування. Робота у середовищі програмування"

Частина 2. 
Основи C#

Теоретичних даних у нас досить, тепер перейдемо до практичної години і на практиці продовжимо знайомитися з мовою С #. Саме практика дозволяє краще зрозуміти, що відбувається і навіщо. Картинки і текст-це добре, але коли ви самі зможете запустити програму і побачити результат, то кращого пояснення придумати просто неможливо.

Звичайно, відразу ж писати складні приклади ми не можемо, тому що програмування - досить складний процес, і треба мати занадто багато базових знань, але прості рішення допоможуть нам. Але це трохи пізніше. Почнемо з того, як створюються пояснення до коду (коментарі), поговоримо трохи про типи даних і просторі імен, закладемо основи, які знадобляться нам надалі, і без яких ми не можемо ще написати візуальний додаток.

2.1. Коментарі

Коментарі - це текст, який не впливає на код програми і не компілюється у вихідний файл. А навіщо тоді вони потрібні? За допомогою коментарів я буду вставляти в код пояснення, щоб вам було легше з ним розбиратися, тому ми розглядаємо їх першими. 

Але коментарі потрібні не тільки для того, щоб пояснити, що відбувається, іншій людині. Коли створюється великий проект, то на його розробку йде досить багато часу, і через два місяці ви вже самі не згадаєте, для чого писали певний код. Коментарі дозволяють залишати замітки і для себе коханого, та й просто роблять код програми більш читабельним.

Існують два типи коментарів - однорядковий і багаторядковий. Однорядковий коментар починається з двох символів / /. Все, що знаходиться в цьому ж рядку далі, - це коментар.

Наприклад,

// оголошення класу EasyCSnarp

class EasyCSharp

{// початок

// Функція Main

public static void Main  ()

{

OutString ()

}

} // Кінець

Символи коментаря // не обов'язково повинні бути на початку рядка. Все, що знаходиться зліва від них, сприймається як код, а все, що знаходиться праворуч до кінця рядки - це коментар, який ігнорується під час компіляції. Я віддаю перевагу ставити коментарі перед рядком коду, який коментую, і іноді в кінці рядка коду.

Багаторядкові коментарі в С # полягають в / * і * /.

Наприклад: / *
Це багаторядковий.

Коментар. * /

Якщо ви будете створювати багаторядкові коментарі в середовищі розробки Visual Studio, то вона автоматично до кожного нового рядка буде додавати до початку символ зірочки.

Наприклад:

/ *
* Це багаторядковий

* Коментар.

* /

Це не є помилкою і іноді навіть зручно. У всякому разі такі коментар виглядає елегантно і зручний для сприйняття.

2.2. Змінна

Поняття "змінна" є одним з ключових в програмуванні. Що то таке і для чого потрібно? Будь-яка програма працює з даними (числами, рядками), які можуть вводитися користувачем або жорстко прописуватися в коді програми. Ці дані треба десь зберігати. Де? Постійні дані зберігаються в тому чи іншому вигляді на жорсткому диску, а тимчасові дані - в оперативній пам'яті комп'ютера.

Під тимчасовими даними розуміється все, що необхідно програмі для розрахунків. Справа в тому, що процесор вміє виконувати математичні операції лише над регістрами процесора (це як би змінні усередині процесора) або оперативною пам'яттю. Тому щоб провести розрахунки над постійними даними, їх необхідно завантажити в оперативну пам'ять.

Припустимо, що ми завантажили дані в пам'ять, але як з ними тепер працювати. У мові асемблера для цього використовуються адреси пам'яті, де зберігаються дані, а в високорівневих мовах, до яких відноситься і С #, такі ділянки пам'яті мають імена.

Ім'я, яке використовується для пам'яті, і є змінна. Ім'я простіше запам'ятати і зручніше використовувати, ніж числові адреси. 

В .NET використовується загальна система типів (Common Type System, CTS). Завдяки спільності типів в .NET, якою б мовою ви не писали програму, типи будуть однакові, і вони однаково будуть зберігатися в пам'яті, а значить, однаково будуть інтерпретуватися програмою і ніяких проблем не виникне.

В більшості мов програмування виділяються два типи даних - прості (числа, рядки, ...) і складні (структури, об'єкти, ...). В .NET і С # немає такого поділу. Ця технологія повністю об'єктна, і навіть прості типи даних є об'єктами, хоча ви можете продовжувати їх використовувати як прості типи в інших мовах. Це зроблено для зручності програмування.

Повністю об'єктні типи даних вже намагалися зробити не раз, наприклад в Java є об'єкти навіть для зберігання чисел. Але це незручно і це занадто марнотратне використання пам'яті, тому в Java є і прості змінні для підвищення швидкості роботи. При цьому, коли потрібно перетворити простий тип в об'єкт і назад, відбувається упаковка і розпакування даних, тобто конвертація простого типу даних в об'єкт і назад.

В .NET типи можна розділити на розмірні та посилальні.

Розмірні - це як раз і є прості типи даних. Якщо вам потрібно зберегти в пам'яті число, то немає сенсу створювати для цього об'єкт, а достатньо просто скористатися розмірним типом. В цьому випадку в пам'яті виділяється тільки необхідну кількість пам'яті.

Посилальні типи - це об'єкти, а ім'я змінної - це посилання на об'єкт. Зверніть увагу, що це посилання, а не покажчик.

У першій колонці табл. 2.1 представлені посилальні типи даних або класи, які реалізують більше прості типи. Що таке клас, ми дізнаємося далі, тому зараз будемо користуватися простішими їх варіантами, які показані в другій колонці, тобто псевдонімами. 

Основні типи описані в просторі імен System, тому якщо ви підключили це простір імен (підключається майстром створення файлів в Visual Studio), то можна вказувати тільки ім'я типу. Якщо простір імен не підключено, то потрібно вказувати повне ім'я, тобто додавати system перед типом даних, наприклад:
System.Int32

При використанні псевдонімів простору імен не потрібно. Навіть якщо не підключено жоден з простору імен, буде коректним запис: int i;

Всі типи даних мають чітко визначений розмір, коли оголошується змінна певного типу, система сама знає, скільки потрібно виділити пам'яті для зберігання даних зазначеного типу. Для простих змінних пам'ять виділяється автоматично і не тільки в .NET, але і в класичних додатках для платформи Win32. Нам не потрібно піклуватися про виділення або знищення пам'яті, всі ці турботи бере на себе система. Ми тільки оголошуємо змінну і працюємо з нею.
 

2.3. Іменування

Від того, як будуть вибиратися імена, залежить читабельність коду програми, а чим зрозуміліше код, тим простіше з ним працювати / писати / супроводжувати.

Давайте спочатку поговоримо про простір імен.

В .NET усі (класи, змінні, структури і т. д.) розбито по просторах імен, що дозволяє позбавитися від можливих конфліктів в іменуванні і, в той же час, використовувати однакові імена в різних просторах. Простір імен - це певна область, всередині якої всі імена повинні бути унікальні.

Простір імен визначається за допомогою ключового слова namespace таким чином:

namespace Ім'я

{

Визначення типів

}

Таким чином, можна визначити власний простір імен, яке діє між фігурними дужками, де можна оголошувати свої типи. Ім'я простору імен може складатися з декількох частин, розділених крапкою. В якості першої частини рекомендується вказувати назву фірми, в якій ви працюєте. Якщо ви є програмістом-одинаком, то можна написати своє власне ім'я.

Наступний приклад показує, як оголосити простір імен з ім'ям TextNamespace для організації MyCompany.

namespace MyCompany.TextNamespace 

{

Визначення типів, класів, змінних

}

Коли ви розробляєте невелику програму, то достатньо просто контролювати іменування і не допускати конфліктів. Але якщо проект великий і ваш код використовується іншими розробниками, то без просторів імен не обійтися.

В С # бажано, щоб навіть маленькі проекти були укладені в якийсь простір імен, і в одному проекті може бути використано кілька просторів.

У своїх проектах ми для кожної збірки створримо свій простір.

Як вибрати простір? Використовувати принцип школа.проект.тематика.

Для доступу до типів, оголошеним всередині певного простору імен, потрібно писати так:

Ім’я_Простору_Имя.Змінна 

Для доступу до змінної можна використовувати і скорочений варіант - тільки ім'я змінної, але для цього має бути виконана одна з двох умов:

  • Ми повинні знаходитися у тому ж самому просторі імен. Тобто якщо змінна оголошена всередині фігурних дужок простору імен і використовується в них же - ім'я простору писати не обов'язково; 
  • Ми повинні підключити простір імен за допомогою оператора using.  

Простір імен System підключається за допомогою рядка:
using System;

В цьому просторі описані всі основні типи даних, основні інструменти та функції роботи з системою. Напевно, усі додатки .NET обов'язково підключають простір імен, інакше навіть типи даних доведеться писати в повному варіанті.

Наприклад, ціле число доведеться писати як system. int32, але якщо написати на початку модуля рядок using system; , тo достатньо буде написати тільки int32 без приставки system на початку.

До речі, якщо не підключити простір імен system, то доступ до консолі для виведення тексту теж доведеться писати в повному вигляді, адже консоль також захована в просторі імен System, і повний формат команди виведення на екран буде: System.Console.WriteLine ("Hello World ! ").

Але так як у нас простір імен system вже підключено, то його писати на початку команди необов'язково.

Як правильно вибирати імена для змінних, методов і класів?

Коли з програмою працює безліч людей або код надто великий, то дуже важливо правильно іменувати змінні. Уже давно загальноприйнятим стандартом є використання на початку імені чогось, що вказує на тип змінної.

Крім вказівки типу змінної, потрібно закласти в ім'я таку назву, яка б відображала сенс її призначення. Ні в якому разі не оголошуйте змінну з однієї або двох безглуздих букв, бо вже через місяць під час налагодження ви не зможете зрозуміти, навіщо потрібна така змінна і для чого ви її використовували

У реальних програмах з однієї літери бувають тільки змінні з ім'ям i чи j, які призначені для лічильників в циклах. Їх призначення заздалегідь визначено, а для інших цілей змінні з такими іменами не використовуються.

Тепер ви повинні визначитися з тим, як записувати імена змінних. Як ми вже розібралися, вони повинні складатися з двох частин: ідентифікатор, що вказує на тип і смислову назву. Записати все це можна по-різному, і щоб побачити різні варіанти, розглянемо приклади.

Нехай, нам потрібний рядок для збереження імені файлу. Оскільки це рядок, то ідентифікатор типу буде s, а змістове ім’я виберемо FileName. Тепер все це можна записати таким чином:

sFileName, s_ FileName, FileName_s, s- FileName, _s_ FileName, FileName.

В C # більшість розробників просто дає зрозумілі імена без вказівки на тип.

Якщо потрібно написати власний метод, то для імені можна відвести окремий префікс, проте імена методів добре видно і без додаткових ідентифікаторів - в кінці імені методу необхідно вказувати круглі дужки і при необхідності, параметри.

При іменуванні компонентів на формі слід розуміти, що працювати з компонентами, у яких імена Button1, Button2 і т.д.. дуже важко. Змінюйте ім'я відразу ж після створення компонента. Якщо цього не зробити відразу, то потім може знадобитися внесення змін в якісь шматки коду, а інколи i чималі.

Якщо призначення змінної, компонента або функції не можна зрозуміти за назвою, то коли прийде час налагодження, ви будете витрачати зайвий час на читання коду. Отже, слід подбати про зручності читання заздалегідь і спростити подальшу роботу. В майбутній роботі ви побачите всі переваги правильного структурування коду і правильного іменування змінних.

Якщо якийсь метод в програмі є обробником подій для компонента чи форми, то його призначення має бути зрозумілим по назві. Для створення імені методу, що викликається у відповідь на подію (якщо натиснена дана кнопка, то виконати …) в Visual Studio по замовчуванню використовується назва компонента та ім’я події.

Наприклад, є компонент з іменем Form1, і для нього створюється обробник подій Load, в цьому випадку назва процедури буде Form1_ Load. Це дуже зручно і краще ніяких змін в імені не робити.

Єдиний випадок, коли перейменування імені обробника події дійсно необхідне - це коли обробник викликається для кількох подій та компонентів. В цьому випадку ім'я має бути таким, щоб ви могли зрозуміти, які компоненти або які події відловлює метод.

Коли ви пишете програму, то пам'ятаєте, що на етапі розробки співвідношення витрачених зусиль до ціни мінімальне. Не економте свій час на правильне оформлення, тому що це погіршить ваше положення під час підтримки програми, а за неї платять набагато менше. За підтримки поганого коду ви будете витрачати надто багато часу на згадування того, що робили рік або два назад. В певний момент може навіть трапитися так, що написання нового продукту з нуля обійдеться дешевше підтримки старого.

2.4. Робота із змінними

Ми навчилися оголошувати змінні, але найцікавіше полягає в тому, як їх використовувати. Давайте подивимося, як можна оголосити змінну типу int, а потім привласнити їй значення:

using System;

class EasyCSharp

{

public static void Main!()

{

int i; / / оголошення змінної
i = 10;

/ / присвоювання зміный значення 10

Console.WriteLine (i);

}

}

Змінні в С # оголошуються в будь-якому місці кода. Оголошення змінної повинно бути виконано до її використання і бажано якомога ближче до її першого використання.

У нашому прикладі в методі Main {} оголошується змінна і , яка буде мати тип int, тобто зберігати цілочисельне значення.

Оголошення змінних відбувається так:

Тип ім’я;

Спочатку пишемо тип змінної, а потім через пропуск ім’я змінної. Щоб присвоїти змінній значення, необхідно використати конструкцію:

ім’я = значення;

У даному прикладі ми присвоюємо змінної i значення 10:

i = 10;

Після цього ділянка пам'яті, на який вказує змінна i, буде містити значення 10.

Кожен оператор повинен закінчуватися крапкою з комою. Це необхідно, щоб компілятор знав, де закінчується один оператор і починається інший. Справа в тому, що оператори необов’язково повинні вписуватися в один рядок, і необов'язково писати тільки по одному оператору в рядок.

Ви легко можете написати:

Int
i;
i
=
10;

Console.WriteLine (i);

У перших двох рядках оголошується змінна i. У наступних трьох рядках змінній і встановлюється значення. При цьому в останньому рядку є ще виведення значення змінної на екран.

Цей код досить таки коректний, все розділено крапкою з комою. Саме по ним компілятор буде визначати окремі оператори.

Проте, так ніхто не пише і ми не будемо. Не варто писати в один рядок дві дії.

Для оголошення змінної і використали псевдонім int. Повна назва типу – System.Int32, і код матиме вигляд:

System.Int32 і;

і=10;

Console.WriteLine(i);

Результат буде тим самим. Проте програмісти пишуть простіше:

int i
і=10;

Console.WriteLine(i);

Мова C# чутлива до регістру букв. Змінна і та змінна І абсолютно різні змінні. Те ж саме із операторами мови: якщо тип називається int, то його неможна писати INT чи Int

Якщо потрібно оголосити кілька змінних одного і того ж типу, то їх можна перерахувати через кому, наприклад:

int i, j;

Тут оголошуються дві цілочисельні змінні з іменами i та j

Тепер подивимося, як визначаються рядки. Наступний приклад оголошує рядок s, присвоює йому значення і виводить вміст на екран:

System.String s;

s = "Hello";

Console.WriteLine (s);

Оголошення рядків відбувається так само, як і цілочисельних змінних. Різниця у привласненні значення. Всі рядки повинні бути укладені в подвійні лапки, які вказують на те, що це текст.

Присвоювати значення змінної можна відразу ж під час оголошення, наприклад:

int i = 10;

У цьому прикладі оголошується змінна і тут же призначається їй значення.

Ставити пропуски навколо знака рівності не обов'язково, і рядок можна було написати так:

int i=10;

Але цей код знову ж виглядає не дуже красиво. Пам'ятайте, що краса - це не тільки пустощі, це ще й зручність.

Найчастіше доводиться працювати з цілими числами і типом даних int. Але також дуже часто пишемо програми, де вже потрібна більш висока точність даних, де «бере участь кома, - використовуються дійсні або дробові числа. Для збереження дробових чисел в .NET найчастіше використовують тип даних double, тому що його розміру цілком достатньо.

Як записується дробове число? У коді програми дробова частина записується незалежно від регіональних налаштувань через крапку:

double d = 1.2; 

У цьому рядку коду оголошується змінна d, якій одразу ж присвоюється значення одна ціла і дві десятих. Та при запуску програми на виконання користувачу доведеться вводити дані відповідно до встановлених у системі регіональних налаштувань.

Що відбувається, якщо намагатися присвоїти значення однієї змінної іншій змінній? Змінна – це ім’я деякої ділянки пам’яті. Коли ми присвоюємо, обидві змінні не будуть вказувати на одну пам'ять. Для простих типів при присвоєнні копіюється значення. Кожна змінна є іменем своєї ділянки пам’яті, і при присвоєнні одне значення копіюється в пам'ять другого.

2.4.1. Рядки і символи

Про рядках ми вже говорили і ми дізналися, що вони укладаються в подвійні лапки:

string str = "Це рядок";

Рядки - не зовсім прості змінні. Коли ви оголошуєте змінну, то система відразу знає, скільки пам'яті потрібно виділити для зберігання значення. А як бути з рядками? Кожен символ в рядку займає два байти (в .NET використовується Unicode для зберігання рядків, але вони можуть, у міру потреби, перетворюватися в інші кодування), але кількість символів у рядку далеко не завжди можливо дізнатися заздалегідь. Як же тоді бути?

В Win32 і класичних додатках мовою C / C++ програміст повинен був перед використанням рядка виділити для неї пам'ять. Найчастіше це робилося одним із двох способів - за допомогою спеціалізованих функцій або за допомогою оголошення масиву із символів. Але обидва способи не ідеальні і при неакуратному використанні приводили до переповнення буферу або виходу за межі виділеної пам'яті. Таким чином, хакер міг змінювати довільні ділянки пам'яті, приводити до краху системи або навіть зламувати комп'ютер.

Нову платформу .NET розробляли максимально безпечною, тому безпека рядків була на першому місці. За онову була взята робота з рядками в Java, де рядки створюються тільки один раз, а система сама виділяє пам'ять для збереження.

Розглянемо приклад коду:

string sсr = "Це рядок";

Тут змінної str присвоюється текст. Компілятор під час виконання може без проблем підрахувати кількість символів в рядку, виділити пам'ять для зберігання тексту і зберегти там дані.

А що якщо змінній присвоюється текст, який вводиться користувачем в якомусь вікні?

В цьому випадку система повинна у власну пам'ять отримати введену інформацію, підрахувати розмір, виділити необхідну пам'ять і зберегти туди введену інформацію.

Тепер подивимося на наступні три рядки коду:

string str;

str = "Це рядок";

str = "Це ще один рядок!";

У першому рядку ми просто оголошуємо змінну з ім'ям str. Ми ще не присвоїли ніякого значення, а значить, str буде просто не ініціалізованою змінною і пам'ять для неї не буде виділена. Якщо спробувати звернутися до такої змінної, відбудеться помилка доступу до непроініціалізованої змінної.

У другому рядку коду змінної присвоюється текст. Саме в цей момент під змінну str буде виділена пам'ять, і в цю пам'ять буде збережений текст. Тут все зрозуміло і легко, тому що система вважає символів (їх 10) і виділяє пам'ять для них.

Наступний рядок коду присвоює все тій же змінній str вже новий текст, в якому вже 20 символів. Але система вже виділила пам'ять, і там вистачає місця тільки для половини символів, куди ж дівати решту?

В .NET не можна змінювати рядки, і при кожній зміні просто створюється новий екземпляр. Що це означає? Незважаючи на те, що str вже проініціалізована і містить значення, пам'ять старого значення буде знищена, і замість неї буде створена нова змінна з необхідною кількістю пам'яті. Відчуваєте міць?

Міць - це добре, але вона б'є по швидкості виконання коду. Якщо при кожній зміні знищувати стару пам'ять і виділяти нову, то ресурси процесора підуть на зайві операції забезпечення зайвої безпеки, адже часто можна обійтися без перестворення змінної. По-перше, безпека все ж важливіше швидкості, а по-друге, є методи роботи з рядками, що вимагають частої зміни рядків, але виконуються дуже швидко, і про них ми ще поговоримо.

Зверніть увагу, що система сама виділяє пам'ять для зберігання потрібного рядка потрібного обсягу. У класичних додатках Win32 програмістам дуже часто доводилося знищувати виділену пам'ять. В .NET в цьому немає необхідності, платформа сама бере на себе всі турботи, по знищенню будь виділенної пам'яті.

Крім рядків в .NET є ще один тип даних, який може зберігати символ. Так, саме один символ, і це тип char:

char ch = 'f'; 

Тут показано, як оголосити змінну ch і привласнити їй значення - символ 'f’. Зверніть увагу, що рядки в С # обрамляються подвійними лапками, а один символ типу char - одинарними. Якщо ж ви присвоюєте рядку один символ, то його потрібно брати в подвійні лапки:

string ch = "f”;

Не дивлячись на те, що ми в змінній ch зберігаємо тільки один символ, його слід брати в подвійні лапки, тому що змінна ch має тип string.

2.4.2. Масиви

Вміти зберігати в пам'яті одне значення будь-якого типу - це добре, але може виникнути необхідність зберігати в пам'яті групу значень однакового типу. Нехай, потрібно зберегти десь кілька чисел, наприклад 10, 50 і 40. Поки не будемо вдаватися в подробиці, навіщо це потрібно і що означають числа, а просто уявімо, що це необхідно.

Для зберігання декількох чисел можна створити три змінні, а можна створити тільки одну змінну, але у вигляді масиву з 3 цілих чисел і звертатися до значень масиву за індексом. Тут можна подумати, що простіше завести все ж три змінних і не думати про якісь масиви. Але що ви будете робити, коли потрібно буде зберегти 100 різних значень? Оголошувати 100 змінних - це катастрофа.

Отже, як же ми можемо оголосити масив певного типу даних? Для цього після типу даних потрібно вказати квадратні дужки. Наприклад, якщо просту числову змінну ми оголошуємо так:

іnt змінна;

то масив з чисел оголошується так: 

int [] змінна;

Тепер у нас є змінна, і ми могли б її використовувати, якщо б не одне дуже велике й жирне АЛЕ - змінна не проініціалізована. Як ми вже знаємо, прості типи даних мають певний розмір, і система може виокремити пам'ять для їх зберігання автоматично, а тут перед нами масив, і ми навіть не знаємо, який у нього розмір (скільки елементів він буде зберігати). Це означає, що система при всьому бажанні не зможе знати скільки пам'яті потрібно зарезервувати під дані масиву.

Щоб проініціалізувати змінну масиву (безпосередньо виділити пам'ять), використовується оператор new, а ініціалізація має вигляд:

Змінна = new тип[кількість елементів];

Нехай, нам потрібен масив із трьох чисел, його можна оголосити і проініціалізувати таким чином:

int [] intArray;
intArray = new int [3];

У першому рядку ми оголошуємо змінну, а в другому присвоюємо їй результат ініціалізації для трьох елементів. Але ж те ж саме можна зробити i одному рядку, відразу ж оголосити змінну і тут же присвоїти їй результат ініціалізаціі, як ми вже робили це з простими типами.

Тільки з простими типами ми не писали слово new. Наступний рядок коду оголошує і ініціалізує змінну в одному рядку:

int [] intArray = new int [3];

Тепер у нас є одна змінна, і ми можемо зберігати в ній три різних значення одночасно. Але як до них звертатися? Дуже просто - після імені змінної у квадратних дужках пишемо індекс елемента, до якого потрібно звернутися. Наступний приклад привласнює елементу з індексом 1 значення 50.

intArray [1] = 50;

І ось тут найцікавіше і дуже важливе - нумерація елементів в масиві.

Елементи масивів в С #, як і в більшості інших мов програмування, нумеруються з нуля. Це означає, що якщо ми створили масив для трьох елементів, то їх індекси будуть 0, 1 і 2, а не 1, 2 і 3. Обов'язково запам'ятайте це, інакше будете часто бачити повідомлення про помилку виходу за межі масиву. Нічого критичного для системи ви зробити не зможете, але ось ваша програма буде завершувати роботу аварійно.

В Win32-додатках вихід за межі масиву, як і вихід за межі рядка, був дуже небезпечний і вів до тих же самих наслідків. Насправді, рядки в Win32 - це різновид масиву, просто це масив одиночних символів, тобто в С # він виглядав би приблизно так:

char [] рядок;

Ось так можна оголосити масив символів і в кожен елемент масиву помістити відповідну букву слова.

Отже, вихід за межі масиву небезпечний для програми або навіть для ОС. Платформа .NET захищає нас від виходу за межі масиву, і ви можете звертатися тільки до виділеної пам'яті. Так, тут ми втрачаємо в гнучкості, але зате виграємо в безпеці. При спробі звернутися до елементу за межами масиву відбудеться помилка.

Тепер подивимося на невеликий приклад, який оголошує і ініціалізує масив з 3 чисел, а потім виводить вміст масиву на екран:

int [] intArray = new int [3];

intArray [0] = 10;

intArray [l] = 50;

intArray [2] = 40;

intArray [3] = 40; // помилка, ми виділили масив з 3 елементів, а називаємо четвертий.

Console. WriteLine (intArray [0]);

Console.WriteLine (intArray 11]);

Console.WriteLine (intArray [2]);

Ініціалізація масиву з допомогою оператора new досить зручна, коли елементи заповнюються розрахунковими даними. Коли кількість елементів та їх значення відомі наперед, то ініціалізація не досить зручна. Наприклад, для створення масиву з назвами днів тижня доведеться писати мінімум 8 рядків – одна для оголошення та ініціалізації і 7 рядків для заповнення масиву значеннями. Це незручно. Тому, коли наперед відомі значення, застосовують другий спосіб ініціалізації:

Змінна = {значення, перераховані через кому}; 

Тут не потрібно оператор new і не потрібно вказувати розмір масиву. Система підрахує кількість елементів у фігурних дужках та виділить відповідну кількість пам’яті.

Наприклад, наступний код показує, як створити масив з назвами днів тижня за один оператор, а після цього на екран виводиться третій елемент масиву:

String[] weekdays = {"Понеділок”,”Вівторок”,”Середа”,”Четвер”,”Пятниця”,”Субота”,”Неділя”};
Concole.WriteLine(weekdays[2]);

Масиви не обмежені тільки одним виміром.

Якщо потрібно зберегти десь таблицю даних, то можна створити двовимірний масив:

int[,] myArray;
myArray=new int[3,3];
 

Тут оголошується двовимірний масив з іменем myArray. Розмірність масиву легко підрахувати, додавши 1 до кількості ком в квадратних дужках. Якщо ком немає, то до 0 додаємо 1 і матимемо одновимірний масив.

В другому рядку відбувається ініціалізація масиву. Зверніть увагу, що в квадратних дужках через кому перераховуються розміри кожної розмірності. Для одновимірного масиву ми вказуємо тільки одне число, а тут потрібно вказувати дві розмірності x та y. В даному випадку система виділяє в пам’яті таблицю для збереження цілих чисел розміром 3х3 елементів.

Наступний приклад показує, як можна оголосити і тут же створити трьохвимірний масив даних:

int[,,] myArray = new int {6,6,5};

Доступ до елементів багатовимірного масиву відбувається так само, як і одновимірного, просто в квадратних дужках потрібно через кому перерахувати індекси кожної розмірності елемента, до якого ви хочете отримати доступ.

Наступний рядок змінює значення елемента двохвимірного масиву з індексом (1,1):

myArray[1,1]=10;

Якщо ви використовуєте тривимірний масив, то в квадратних дужках доведеться перераховувати значення всіх трьох розмірностей.
 

2.4.3. Перерахування   

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

В даному випадку кращим прикладом будуть служити дні тижня. Припустимо, що, треба мати змінну, в якій потрібно зберегти поточний день тижня. Як це можна зробити? Щоб простіше було визначити, треба просто зрозуміти, що таке день тижня, і в якому типі даних його уявити? Можна уявити його рядком але це буде вже не день тижня, а всього лише назва дня тижня. Можна уявити його числом від 1 до 7 або від 0 до 6 (кому як зручніше) але це буде номер дня, але не день тижня. Як же тоді бути? Чому разробники Visual Studio не подбали про таку ситуацію і не впровадили тип даних, який буде саме днем тижня? Можливо і впровадили, проте подібні типи даних ми можемо легко створювати самі з допомогою перерахувань enum.

Отже, оголошення перерахування enum виглядає наступним чином:

enum ім'я {Значення через кому};

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

enum WeekDays {Monday, Tuesday, Wednesday,Thursday, Friday, Saturday, Sunday};

От і все. У фігурних дужках написані імена днів тижня «англійською», цілком зрозумілі імена, які можна використовувати в додатку. Тепер у нас є новий тип даних weekDays, ми можемо оголошувати змінні цього типу, присвоювати їм значення днів тижня.

Наприклад:

WeekDays day;

day = WeekDays.Thursday; 

У першому рядку ми оголосили змінну day типу WeekDays. Це оголошення ідентично створенню змінних будь-якого іншого типу. У другому рядку змінній присвоюється значення п’ятниці. Як це робиться? Потрібно просто написати тип даних, а через крапку вказати те значення перерахування, яке ви хочете привласнити: WeekDays.Friday.

Щоб показати перерахування у всій красі, розглянемо невеличкий приклад, який показує різні варіанти використання перерахування.

Код прикладу:

class Program

{

enum WeekDays { Monday, Tuesday, Wednesday,Thursday, Friday, Saturday, Sunday } ;

static void Main(string[] args)

{

// масив з назвами днів тижня на українській мові

String[] WeekDaysNames = {"Понеділок","Вівторок","Середа","Четвер","Пятниця","Субота","Неділя"};

WeekDays day = WeekDays.Friday;

// виведення дня тижня в різних форматах

Console.WriteLine("Сьогоднi " + day);

int dayIndex = (int)day + 1;

Console.WriteLine("Номер дня " + dayIndex);

Console.WriteLine("Сьогоднi " + WeekDaysNames[(int)day]);

// вот так можна робити перевірку порівнянням

if (day == WeekDays.Friday)
Console.WriteLine("Скоро вихiдний");

Console.ReadLine();

}

}

Значення перерахувань можуть бути написані тільки англійською і не містити пропусків. В такому випадку зручно використовувати масив з назв на українській мові а потім вивести відповідне значення на екран:

String[] WeekDaysNames = {"Понеділок","Вівторок","Середа","Четвер","Пятниця","Субота","Неділя"};

Console.WriteLine("Сьогоднi " + WeekDaysNames[(int)day]);

За замовчуванням елементи перерахування отримують індекси (значення) від 0. А що якщо ми хочемо, щоб вони мали індекси, починаючи зі ста? В цьому випадку можна першому елементу присвоїти потрібний нам індекс. Це робиться простим привласненням:

enum MyColors

{
Red = 100; 

Green,

Blue

Тут наведене нове перерахування кольорів, щоб воно було трохи менше за розміром. Тепер, якщо привести червоний колір до числа, то ми побачимо 100, у випадку з зеленим ми побачимо 101, а для синього буде 102.
Ви можете призначити кожному елементу свої власні індекси:

enum MyColors

{

Red = 100,  

Green = 110,

Blue = 120

2.5. Найпростіша математика

Змінні вводяться для того, щоб проводити над ними певні обчислення.
В мові C# є наступні математичні оператори:

  • додавання (+)  
  • віднімання (-)  
  • множення (*)  
  • ділення (/)
     

Нехай ми ввели змінну і, якій присвоїли значення 10, а потім помножимо цю змінну на 2 і розділимо на 5. В коді це буде виглядати наступним чином:

int i;
i = 10;

i = i * 2/5;

Console.WriteLine (i);

Як бачите, писати математичні обчислення не так вже й складно. Змінній i просто присвоюємо результат математичних обчислень.

Існують і більш скорочені варіанти математичних операцій:

  • збільшити значення змінної на 1 (+ +);  
  • зменшити значення змінної на 1 (--);  
  • додати до змінної (+ =);  
  • відняти від змінної (- =);  
  • помножити змінну на значення (* =);  
  • розділити змінну на значення (/ =). 

Ось тут потрібні деякі коментарі. Припустимо, що ми хочемо збільшити значення змінної i на 1. Для цього можна написати наступний рядок коду:

int i = 10;

i = i + 1; 

В першому рядку ми оголошуємо змінну і і присвоюємо їй значення 10. В другому рядку3 значення змінної збільшується на 1, отримуємо в результаті число 11.

Та можна застосувати більш короткий варіант:

int i = 10;

i = i + +;

У другому рядку значення змінної збільшується на 1, і отримуємо число 11.

Тепер подивимося як можна зменшувати значення змінної :

1). int i = 10;
i = i - 1;

2). int i = 10;
i = i - -;

В результаті у змінній i після виконання цього коду