У мові C# є такі примітивні типи даних:
bool: зберігає значення true чи false (логічні літерали). Представлений системним типом System.Boolean
bool alive = true;
bool isDead = false;
byte: зберігає ціле число від 0 до 255 та займає 1 байт. Представлений системним типом System.Byte
byte bit1 = 1;
byte bit2 = 102;
sbyte: зберігає ціле число від -128 до 127 і займає 1 байт. Представлений системним типом System.SByte
sbyte bit1 = -101;
sbyte bit2 = 102;
short: зберігає ціле число від -32768 до 32767 і займає 2 байти. Представлений системним типом System.Int16
short n1 = 1;
short n2 = 102;
ushort: зберігає ціле число від 0 до 65535 і займає 2 байти. Представлений системним типом System.UInt16
ushort n1 = 1;
ushort n2 = 102;
int: зберігає ціле число від -2147483648 до 2147483647 і займає 4 байти. Представлений системним типом System.Int32. Всі цілі літерали за замовчуванням представляють значення типу int:
int a = 10;
int b = 0b101; // бинарная форма b =5
int c = 0xFF; // шестнадцатеричная форма c = 255
uint: зберігає ціле число від 0 до 429 496 72 95 і займає 4 байти. Представлений системним типом System.UInt32
uint a = 10;
uint b = 0b101;
uint c = 0xFF;
long: зберігає ціле число від -9223372036854775808 до 9223372036854775807 і займає 8 байт. Представлений системним типом System.Int64
long a = -10;
long b = 0b101;
long c = 0xFF;
ulong: зберігає ціле число від 0 до 18446744073709551615 і займає 8 байт. Представлений системним типом System.UInt64
ulong a = 10;
ulong b = 0b101;
ulong c = 0xFF;
float: зберігає число з плаваючою точкою від -3.4 * 1038 до 3.4 * 1038 і займає 4 байти. Представлений системним типом System.Single
double: зберігає число з плаваючою точкою від ±5.0*10-324 до ±1.7*10308 і займає 8 байти. Представлений системним типом System.Double
decimal: зберігає десяткове дробове число. Якщо використовується без десяткової коми, має значення від ±1.0*10-28 до ±7.9228*1028, може зберігати 28 знаків після коми і займає 16 байт. Представлений системним типом System.Decimal
char: зберігає одиночний символ у кодуванні Unicode і займає 2 байти. Представлений системним типом System.Char. Цьому типу відповідають символьні літерали:
char a = 'A';
char b = '\x5A';
char c = '\u0420';
string: зберігає набір символів Unicode. Представлений системним типом System.String. Цьому типу відповідають рядкові литералы.
string hello = "Hello";
string word = "world";
object: може зберігати значення будь-якого типу даних і займає 4 байти на 32-розрядній платформі та 8 байт на 64-розрядній платформі. Представлений системним типом System.Object, який є базовим для всіх інших типів та класів .NET.
object a = 22;
object b = 3.14;
object c = "hello code";
Наприклад, визначимо кілька змінних різних типів і виведемо їх значення на консоль:
string name = "Tom";
int age = 33;
bool isEmployed = false;
double weight = 78.65;
Console.WriteLine($"Ім'я: {name}");
Console.WriteLine($"Вік: {age}");
Console.WriteLine($"Вага: {weight}");
Console.WriteLine($"Працює: {isEmployed}");
Нерідко виникає необхідність вивести на консоль в одному рядку значення відразу кількох змінних. У цьому випадку ми можемо використовувати прийом, який називається інтерполяцією:
string name = "Tom";
int age = 34;
double height = 1.7;
Console.WriteLine($"Ім'я: {name} Вік: {age} Зріст: {height}м");
Є інший спосіб виведення на консоль відразу кількох значень:
string name = "Tom";
int age = 34;
double height = 1.7;
Console.WriteLine("Ім'я: {0} Вік: {2} Зріст: {1}м", name, height, age);
Тут бачимо, що рядок в Console.WriteLine містить деякі числа у фігурних дужках: {0}, {1}, {2}. Це плейсхолдери, замість яких під час виведення рядка на консоль будуть підставлятися деякі значення. Значення, що підставляються, вказуються після рядка через кому.
При цьому важливим є порядок подібних плейсхолдерів. Наприклад, у разі після рядка першої вказана змінна name, потім height і потім age. Тому значення змінної name всмоктуватиметься замість першого плейсхолдера - {0} (нумерація починається з нуля), height - замість {1}, а age - замість {2}. Тому в підсумку під час виведення на консоль рядок
Console.Write
Крім Console.WriteLine() можна також використовувати метод Console.Write(), він працює так само за тим винятком, що не додає перехід на наступний рядок, тобто наступний консольний висновок виводитиметься на тому ж рядку.
string name = "Tom";
int age = 34;
double height = 1.7;
Console.Write($"Ім'я: {name} Вік: {age} Зріст: {height}м");
Консольне введення
Окрім виведення інформації на консоль, ми можемо отримувати інформацію з консолі. Для цього призначено метод Console.ReadLine(). Він дозволяє отримати введений рядок.
Console.Write("Введіть своє ім'я:");
string name = Console.ReadLine();
Console.WriteLine($"Привіт{name}");
У разі все, що вводить користувач, з допомогою методу Console.ReadLine() передається змінну name.
Особливістю методу Console.ReadLine() є те, що він може рахувати інформацію з консолі тільки у вигляді рядка. Крім того, можлива ситуація, коли для методу Console.ReadLine не виявиться доступних для зчитування рядків, тобто коли йому нема чого зчитувати, він повертає значення null, тобто, грубо кажучи, фактично відсутність значення. І щоб відобразити цю ситуацію ми визначаємо змінну name, яку отримуємо введення з консолі, як змінну типу string?. Тут string вказує, що змінна може зберігати значення типу string, тобто рядки. А знак питання? показує, що змінна також може зберігати значення null, тобто насправді не мати ніякого значення.
Однак, може виникнути питання, як нам бути, якщо, припустимо, ми хочемо ввести вік у змінну типу int або іншу інформацію у змінні типу double чи decimal? За замовчуванням платформа .NET надає ряд методів, які дозволяють конвертувати різні значення до типів int, double і т.д. Деякі з цих методів:
Convert.ToInt32() (перетворює до типу int)
Convert.ToDouble() (перетворює до типу double)
Convert.ToDecimal() (перетворює до типу decimal)
Console.Write("Введіть ім'я:");
string name = Console.ReadLine();
Console.Write("Введіть вік:");
int age = Convert.ToInt32(Console.ReadLine());
Console.Write("Введіть зростання:");
double height = Convert.ToDouble(Console.ReadLine());
Console.Write("Введіть розмір зарплати:");
decimal salary = Convert.ToDecimal(Console.ReadLine());
Console.WriteLine($"Ім'я: {name} Вік: {age} Зростання: {height}м Зарплата: {salary}$");
C# використовується більшість операцій, які застосовуються і в інших мовах програмування. Операції представляють певні дії над операндами – учасниками операції. Як операнда може виступати змінною або будь-яке значення (наприклад, число). Операції бувають унарними (виконуються над одним операндом), бінарними – над двома операндами та тернарними – виконуються над трьома операндами. Розглянемо всі види операцій.
Бінарні арифметичні операції:
+
Операція додавання двох чисел:
int x = 10;
int z = x + 12; // 22
-
Операція віднімання двох чисел:
int x = 10;
int z = x – 6; // 4
*
Операція множення двох чисел:
int x = 10;
int z = x * 5; // 50
/
операція поділу двох чисел:
int x = 10;
int z = x/5; // 2
double a = 10;
double b = 3;
double c = a/b; // 3.33333333
При розподілі варто враховувати, що якщо обидва операнда представляють цілі числа, то результат буде округлятися до цілого числа:
double z = 10/4; //Результат дорівнює 2
Незважаючи на те, що результат операції в результаті поміщається в змінну типу double, яка дозволяє зберегти дробову частину, але в самій операції беруть участь два літерали, які за умовчанням розглядаються як об'єкти int, тобто цілі числа, і результат те ж буде цілий.
Для виходу з цієї ситуації необхідно визначати літерали або змінні, що беруть участь в операції саме як типи double або float:
double z = 10.0/4.0; //Результат дорівнює 2.5
%
Операція отримання залишку від цілісного поділу двох чисел:
double x = 10.0;
double z = x%4.0; //Результат дорівнює 2
Також є ряд унарних операцій, у яких бере участь один операнд:
Особливий клас операцій представляють порозрядні операції. Вони виконуються над окремими розрядами числа. У цьому плані числа розглядаються у двійковому поданні, наприклад, 2 у двійковому поданні 10 і має два розряди, число 7 - 111 і має три розряди.
&(логічне множення)
Множення проводиться порозрядно, і якщо в обох операнда значення розрядів дорівнює 1, то операція повертає 1, інакше повертається число 0. Наприклад:
int x1 = 2; //010
int y1 = 5;//101
Console.WriteLine(x1&y1); // виведе 0
int x2 = 4; //100
int y2 = 5; //101
Console.WriteLine(x2 & y2); // виведе 4
У першому випадку ми два числа 2 і 5. 2 у двійковому вигляді представляє число 010, а 5 - 101. Порозрядно помножимо числа (0*1, 1*0, 0*1) й у результаті отримаємо 000.
У другому випадку у нас замість двійки число 4, у якого в першому розряді 1, так само як і у числа 5, тому отримаємо (1*1, 0*0, 0 *1) = 100, тобто число 4 в десятковий формат.
| (логічне додавання)
Схоже на логічне множення, операція також здійснюється за двійковими розрядами, але тепер повертається одиниця, якщо хоча б у одного числа в даному розряді є одиниця. Наприклад:
int x1 = 2; //010
int y1 = 5;//101
Console.WriteLine(x1|y1); // виведе 7 - 111
int x2 = 4; //100
int y2 = 5;//101
Console.WriteLine(x2 | y2); // виведе 5 - 101
^ (логічне виключне АБО)
Також цю операцію називають XOR, нерідко її застосовують для простого шифрування:
int x = 45; // Значення, яке треба зашифрувати - у двійковій формі 101101
int key = 102; //Нехай це буде ключ - у двійковій формі 1100110
int encrypt = x ^ key; //Результатом буде число 1001011 або 75
Console.WriteLine($"Зашифроване число: {encrypt}") ;
int decrypt = encrypt^key; // Результатом буде вихідне число 45
Console.WriteLine($"Розшифроване число: {decrypt}");
Тут знову ж таки проводяться порозрядні операції. Якщо значення поточного розряду в обох чисел різні, то повертається 1, інакше повертається 0. Таким чином, ми отримуємо з 9^5 як результат число 12. І щоб розшифрувати число, ми застосовуємо ту ж операцію до результату.
~ (логічне заперечення чи інверсія)
Ще одна порозрядна операція, яка інвертує всі розряди: якщо значення розряду дорівнює 1, воно стає рівним нулю, і навпаки.
int x = 12; // 00001100
Console.WriteLine(~x); // 11110011 або -13
Подання негативних чисел
Для запису чисел зі знаком C# застосовується додатковий код (two's complement), у якому старший розряд є знаковим. Якщо його значення дорівнює 0, то число позитивне, та його двійкове уявлення не відрізняється від уявлення беззнакового числа. Наприклад, 0000 0001 у десятковій системі 1.
Якщо старший розряд дорівнює 1, ми маємо справу з негативним числом. Наприклад, 1111 1111 у десятковій системі становить -1. Відповідно, 1111 0011 становить -13.
Щоб отримати з позитивного числа негативне, його потрібно інвертувати та додати одиницю:
int x = 12;
int y = ~x;
y += 1;
Console.WriteLine(y); // -12
Операції зсуву
Операції зсуву також виконуються над розрядами чисел. Зсув може відбуватися праворуч і ліворуч.
x<<y - зсуває число x вліво на y розрядів. Наприклад, 4<<1 зрушує число 4 (яке в двійковому поданні 100) на один розряд вліво, тобто в результаті виходить 1000 або число 8 у десятковому поданні.
x>>y - зсуває число x праворуч на y розрядів. Наприклад, 16>>1 зсуває число 16 (яке в двійковому поданні 10000) на один розряд праворуч, тобто в результаті виходить 1000 або число 8 у десятковому поданні.
Таким чином, якщо вихідне число, яке треба зрушити в ту чи іншу строну, ділиться на два, то фактично виходить множення чи поділ на два. Тому подібну операцію можна використовувати замість безпосереднього множення чи поділу на два. Наприклад:
int a = 16; // у двійковій формі 10000
int b = 2; // у двійковій формі
int c = a << b; // Зсув числа 10000 вліво на 2 розряди, дорівнює 1000000 або 64 у десятковій системі
Console.WriteLine($"Зашифроване число: {c}") ; // 64
int d = a >> b; // Зсув числа 10000 вправо на 2 розряди, що дорівнює 100 або 4 в десятковій системі
Console.WriteLine($"Зашифроване число: {d}"); // 4
При цьому числа, які беру участь в операціях, необов'язково мають бути кратними 2:
int a = 22; // у двійковій формі 10110
int b = 2; // у двійковій формі
int c = a << b; // Зсув числа 10110 вліво на 2 розряди, дорівнює 1011000 або 88 у десятковій системі
Console.WriteLine($"Зашифроване число: {c}") ; // 88
int d = a >> b; // Зсув числа 10110 вправо на 2 розряди, що дорівнює 101 або 5 в десятковій системі
Console.WriteLine($"Зашифроване число: {d}"); // 5
Операції присвоєння встановлюють значення. В операціях присвоєння беруть участь два операнди, причому лівий операнд може представляти тільки модифікований іменований вираз, наприклад, змінну
Як і в багатьох інших мовах програмування, C# є базова операція присвоєння =, яка присвоює значення правого операнда лівому операнду:
int number = 23;
Тут змінній number присвоюється число 23. Змінна number представляє лівий операнд, якому присвоюється значення правого операнда, тобто 23.
Також можна виконувати множинне присвоєння відразу кількох змінним одночасно:
int a, b, c;
a = b = c = 34;
Варто зазначити, що операції надання мають низький пріоритет. І спочатку обчислюватиметься значення правого операнда і потім буде присвоєння цього значення лівому операнду. Наприклад:
int a, b, c;
a = b = c = 34*2/4; // 17
Спочатку обчислюватиметься вираз 34*2/4, потім отримане значення буде присвоєно змінним.
Крім базової операції присвоєння C# є ще ряд операцій:
<<=: привласнення після зсуву розрядів вліво. Надає лівому операнду результат зсуву його бітового подання вліво на певну кількість розрядів, що дорівнює значенню правого операнда: A <<= B еквівалентно A = A << B
>>=: привласнення після зсуву розрядів праворуч. Надає лівому операнду результат зсуву його бітового подання вправо на певну кількість розрядів, що дорівнює значенню правого операнда: A >>= B еквівалентно A = A >> B
Застосування операцій присвоєння:
int a = 10;
a + = 10; // 20
a -= 4; // 16
a * = 2; // 32
a / = 8; // 4
a <<= 4; // 64
a >>= 2; // 16
Операції присвоєння є правоасоціативними, тобто виконуються праворуч наліво. Наприклад:
int a = 8;
int b = 6;
int c = a + = b - = 5; // 9
В даному випадку виконання виразу йтиме таким чином:
b -= 5 (6-5=1)
a += (b-=5) (8+1 = 9)
c = (a + = (b-=5)) (c = 9)
Явні перетворення
При явних перетвореннях (explicit conversion) ми маємо застосувати операцію перетворення (операція ()). Суть операції перетворення типів у тому, що перед значенням вказується в дужках тип, якого треба привести дане значение:
int a = 4;
int b = 6;
byte c = (byte)(a+b);
Окремий набір операцій представляє умовні висловлювання. Такі операції повертають логічне значення, тобто значення типу bool: true, якщо вираз істинний, і false, якщо вираз хибний. До подібних операцій належать операції порівняння та логічні операції.
Операції порівняння
В операціях порівняння порівнюються два операнда і повертається значення типу bool - true, якщо вираз вірний, і false, якщо вираз невірний.
==
Порівнює два операнди на рівність. Якщо вони рівні, операція повертає true, якщо не рівні, то повертається false:
int a = 10;
int b = 4;
bool c = a == b; // false
!=
Порівнює два операнди і повертає true, якщо операнди не рівні, і false, якщо вони рівні.
int a = 10;
int b = 4;
bool c = a != b; // true
bool d = a!=10; // false
<
Операція "менша ніж". Повертає true, якщо перший операнд менший за другий, і false, якщо перший операнд більший за другий:
int a = 10;
int b = 4;
bool c = a < b; // false
>
Операція "більше ніж". Порівнює два операнди і повертає true, якщо перший операнд більший за другий, інакше повертає false:
int a = 10;
int b = 4;
bool c = a > b; // true
bool d = a > 25; // false
<=
Операція "менше або одно". Порівнює два операнди і повертає true, якщо перший операнд менше або дорівнює другому. Інакше повертає false.
int a = 10;
int b = 4;
bool c = a <= b; // false
bool d = a <= 25; // true
>=
Операція "більше чи одно". Порівнює два операнди і повертає true, якщо перший операнд більше або дорівнює другому, інакше повертається false:
int a = 10;
int b = 4;
bool c = a >= b; // true
bool d = a >= 25; // false
Операції <, > <=, >= мають більший пріоритет ніж == і !=.
Логічні операції
Також у C# визначено логічні оператори, які повертають значення типу bool. Як операнди вони приймають значення типу bool. Як правило, застосовуються до відносин і поєднують кілька операцій порівняння.
|
Операція логічного складання чи логічне АБО. Повертає true, якщо хоча б один із операндів повертає true.
bool x1 = (5> 6) | (4 < 6); // 5 > 6 – false, 4 < 6 – true, тому повертається true
bool x2 = (5> 6) | (4> 6); // 5 > 6 – false, 4 > 6 – false, тому повертається false
&
Операція логічного множення чи логічне І. Повертає true, якщо обидва операнди одночасно рівні true.
bool x1 = (5 > 6) & (4 < 6); // 5 > 6 – false, 4 < 6 – true, тому повертається false
bool x2 = (5 < 6) & (4 < 6); // 5 < 6 – true, 4 < 6 – true, тому повертається true
||
Операція логічного складання. Повертає true, якщо хоча б один із операндів повертає true.
bool x1 = (5> 6) | (4 < 6); // 5 > 6 – false, 4 < 6 – true, тому повертається true
bool x2 = (5> 6) | (4> 6); // 5 > 6 – false, 4 > 6 – false, тому повертається false
&&
Операція логічного множення. Повертає true, якщо обидва операнди одночасно рівні true.
bool x1 = (5 > 6) && (4 < 6); // 5 > 6 – false, 4 < 6 – true, тому повертається false
bool x2 = (5 < 6) && (4 < 6); // 5 < 6 – true, 4 < 6 – true, тому повертається true
!
Операція логічного заперечення. Виробляється над одним операндом і повертає true, якщо операнд дорівнює false. Якщо операнд дорівнює true, операція повертає false:
bool a = true;
bool b =! // false
^
Операція виключає АБО. Повертає true, якщо перший, або другий операнд (але не одночасно) рівні true, інакше повертає false
bool x5 = (5 > 6) ^ (4 < 6); // 5 > 6 – false, 4 < 6 – true, тому повертається true
bool x6 = (50>6)^(4/2<3); // 50 > 6 - true, 4/2 < 3 - true, тому повертається false
Тут у нас дві пари операцій та || (а також & і &&) виконують схожі дії, однак вони не рівнозначні.
У виразі z = x | y; обчислюватимуться обидва значення - x і y.
У виразі ж z = x | | y; спочатку буде обчислюватися значення x, і якщо воно дорівнює true, то обчислення значення y вже не має сенсу, так як у нас у будь-якому випадку вже z буде одно true. Значення y буде обчислюватися тільки в тому випадку, якщо x дорівнює false
Те саме стосується пари операцій &/&&. У виразі z=x&y; обчислюватимуться обидва значення - x і y.
У виразі ж z=x&&y; спочатку буде обчислюватися значення x, і якщо воно дорівнює false, то обчислення значення y вже не має сенсу, так як у нас у будь-якому випадку вже z буде дорівнює false. Значення y буде обчислюватися тільки в тому випадку, якщо x дорівнює true
Тому операції || і && більш зручні у обчисленнях, оскільки дозволяють скоротити час на обчислення значення виразу, і тим самим підвищують продуктивність. А операції | & більше підходять для виконання порозрядних операцій над числами.
Умовні конструкції - один із базових компонентів багатьох мов програмування, які спрямовують роботу програми по одному зі шляхів залежно від певних умов. Однією з таких конструкцій у мові програмування C# є конструкція if.
Конструкція if/else перевіряє істинність певної умови та залежно від результатів перевірки виконує певний код.
Її найпростіша форма складається з блоку if:
if(умова)
{
виконувані інструкції
}
Після ключового слова if ставиться умова. Умова повинна представляти значення bool. Це може бути безпосередньо значення типу bool або результат умовного виразу або іншого виразу, який повертає значення тіа bool. І якщо ця умова є істинною (рівно true), то спрацьовує код, який поміщений далі після умови всередині фігурних дужок.
Наприклад:
int num1 = 8;
int num2 = 6;
if(num1 > num2){
Console.WriteLine($"Число {num1} більше числа {num2}");
}
В даному випадку у нас перше число більше за друге, тому вираз num1 > num2 істинний і повертає true, отже, управління переходить до рядка Console.WriteLine("Число {num1} більше числа {num2}");
Якщо блок if містить одну інструкцію, ми можемо його скоротити, прибравши фігурні дужки:
int num1 = 8;
int num2 = 6;
if (num1 > num2)
Console.WriteLine($"Число {num1} більше числа {num2}");
// або так
if (num1 > num2) Console.WriteLine($"Число {num1} більше числа {num2}");
Також ми можемо поєднати відразу кілька умов, використовуючи логічні оператори:
int num1 = 8;
int num2 = 6;
if(num1 > num2 && num1==8)
{
Console.WriteLine($"Число {num1} більше числа {num2}");
}
У разі блок if буде виконуватися, якщо num1 > num2 дорівнює true і num1==8 дорівнює true.
Вираз else
Але що, якщо ми захочемо, щоб у разі недотримання умови також виконувались якісь дії? У цьому випадку ми можемо додати блок else:
int num1 = 8;
int num2 = 6;
if(num1 > num2)
{
Console.WriteLine($"Число {num1} більше числа {num2}");
}
else
{
Console.WriteLine($"Число {num1} менше числа {num2}");
}
Блок else виконується, якщо умова після if помилково, тобто одно false. Якщо блок else містить тільки одну інструкцію, то знову ж таки ми можемо його скоротити, прибравши фігурні дужки:
int num1 = 8;
int num2 = 6;
if(num1 > num2)
Console.WriteLine($"Число {num1} більше числа {num2}");
else
Console.WriteLine($"Число {num1} менше числа {num2}");
else if
Але в прикладі вище при порівнянні чисел ми можемо нарахувати три стани: перше число більше за друге, перше число менше за друге і числа рівні. Використовуючи конструкцію else if, ми можемо обробляти додаткові умови:
int num1 = 8;
int num2 = 6;
if(num1 > num2)
{
Console.WriteLine($"Число {num1} більше числа {num2}");
}
else if (num1 <num2)
{
Console.WriteLine($"Число {num1} менше числа {num2}");
}
else
{
Console.WriteLine("Число num1 дорівнює числу num2");
}
При необхідності можна додати кілька виразів else if:
string name = "Alex";
if (name == "Tom")
Console.WriteLine("Вас звуть Tomas");
else if (name == "Bob")
Console.WriteLine("Вас звуть Robert");
else if (name == "Mike")
Console.WriteLine("Вас звуть Michael");
else
Console.WriteLine("Невідоме ім'я");
Тернарна операція
Тернарна операція також дозволяє перевірити деяку умову і в залежності від його істинності виконати деякі дії. Вона має наступний синтаксис:
[перший операнд - умова]? [другий операнд] : [третій операнд]
Тут одразу три операнда. Залежно від умови тернарна операція повертає другий чи третій операнд: якщо умова дорівнює true, то повертається другий операнд; якщо умова дорівнює false, то третя. Наприклад:
int x=3;
int y=2;
int z = x < y? (x+y): (x-y);
Console.WriteLine(z); // 1
Тут перший операнд (тобто умова) є виразом x < y. Якщо воно рівне true, то повертається другий операнд - (x + y), тобто результат операції складання. Якщо умова дорівнює false, повертається третій операнд - (x-y).
Результат тернарної операції (тобто другий чи третій операнд залежно від умови) надається змінної z.
Використовуйте оператор switch, щоб вибрати один із багатьох блоків коду для виконання.
switch(expression)
{
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
break;
}
Ось як це працює:
Вираз switch обчислюється один раз
Значення виразу порівнюється зі значеннями кожного випадку
Якщо є збіг, виконується відповідний блок коду
Ключові слова break і default будуть описані далі в цьому розділі
У прикладі нижче використовується номер дня тижня для обчислення назви дня тижня:
int day = 4;
switch (day)
{
case 1:
Console.WriteLine("Monday");
break;
case 2:
Console.WriteLine("Tuesday");
break;
case 3:
Console.WriteLine("Wednesday");
break;
case 4:
Console.WriteLine("Thursday");
break;
case 5:
Console.WriteLine("Friday");
break;
case 6:
Console.WriteLine("Saturday");
break;
case 7:
Console.WriteLine("Sunday");
break;
}
// Outputs "Thursday" (day 4)
Ключове слово break
Коли C# досягає ключового слова break, він виривається з блоку switch.
Це призупинить виконання додаткового коду та тестування регістру всередині блоку.
Коли збіг знайдено, і робота зроблена, настав час перерви. Більше тестування не потрібно.
Перерва може заощадити багато часу на виконання, оскільки воно «ігнорує» виконання всього решти коду в блоці перемикання.
Ключове слово за умовчанням
Ключове слово за замовчуванням є необов’язковим і визначає певний код для запуску, якщо немає відповідності регістру:
int day = 4;
switch (day)
{
case 6:
Console.WriteLine("Today is Saturday.");
break;
case 7:
Console.WriteLine("Today is Sunday.");
break;
default:
Console.WriteLine("Looking forward to the Weekend.");
break;
}
// Outputs "Looking forward to the Weekend."
Цикли є керуючими конструкціями, дозволяючи в залежності від певних умов виконувати деяку дію багато разів. У C# є такі види циклів:
for
foreach
while
do...while
Цикл for
Цикл for має таке формальне визначення:
for ([дії_до_виконання_циклу]; [умова]; [дії_після_виконання])
{
// дії
}
Оголошення циклу for складається із трьох частин. Перша частина оголошення циклу – деякі дії, які виконуються один раз до виконання циклу. Зазвичай тут визначаються змінні, які будуть використовуватись у циклі.
Друга частина - умова, за якої виконуватиметься цикл. Поки умова дорівнює true, виконуватиметься цикл.
І третина - деякі дії, які виконуються після завершення блоку циклу. Ці дії виконуються щоразу після завершення блоку циклу.
Після оголошення циклу у фігурних дужках розміщуються самі дії циклу.
Розглянемо стандартний цикл for:
for (int i = 1; i < 4; i++)
{
Console.WriteLine(i);
}
Тут перша частина оголошення циклу - int i = 1 - створює та ініціалізує змінну i.
Друга частина - умова i < 4. Тобто доки змінна i менше 4, виконуватиметься цикл.
І третина - дії, що виконуються після завершення дій із блоку циклу - збільшення змінної i на одиницю.
Весь процес циклу можна представити так:
Визначається змінна int i = 1
Перевіряється умова i < 4. Воно істинне (оскільки 1 менше 4), тому виконується блок циклу, а саме інструкція Console.WriteLine(i), яка виводить на консоль значення змінної i
Блок циклу закінчив виконання, тому виконується третина оголошення циклу - i++. Після цього змінна i дорівнюватиме 2.
Знову перевіряється умова i < 4. Воно істинне (оскільки 2 менше 4), тому знову виконується блок циклу - Console.WriteLine(i)
Блок циклу закінчив виконання, тому знову виконується вираз i ++. Після цього змінна i дорівнюватиме 3.
Знову перевіряється умова i < 4. Воно істинне (оскільки 3 менше 4), тому знову виконується блок циклу - Console.WriteLine(i)
Блок циклу закінчив виконання, тому знову виконується вираз i ++. Після цього змінна i дорівнюватиме 4.
Знову перевіряється умова i < 4. Тепер вона заперечує false, оскільки значення змінної i НЕ менше 4, тому цикл завершує виконання. Далі вже виконується решта програми, яка йде після циклу
У результаті блок циклу спрацює 3 рази, поки значення i не стане рівним 4. І щоразу це значення збільшуватиметься на 1. Одноразове виконання блоку циклу називається ітерацією. Таким чином, тут цикл виконає три ітерації. Результат роботи програми:
Якщо блок циклу for містить одну інструкцію, ми можемо його скоротити, прибравши фігурні свобки:
for (int i = 1; i < 4; i++)
Console.WriteLine(i);
// або так
for (int i = 1; i < 4; i++) Console.WriteLine(i);
При цьому необов'язково саме у першій частині циклу оголошувати змінну, а третій частині змінювати її значення - це можуть бути будь-які дії. Наприклад:
var i = 1;
for (Console.WriteLine("Початок виконання циклу"); i < 4; Console.WriteLine($"i = {i}"))
{
i++;
}
Тут знову ж таки цикл спрацьовує, поки змінна i менше 4, тільки збільшення змінної i відбувається в блоці циклу. Консольний висновок цієї програми:
Початок виконання циклу
i = 2
i = 3
i = 4
Нам необов'язково вказувати всі умови під час оголошення циклу. Наприклад, ми можемо написати так:
int i = 1;
for (; ;)
{
Console.WriteLine($"i = {i}");
i++;
}
Формально визначення циклу залишилося тим самим, тільки тепер блоки у визначенні у нас порожні: for(;;). У нас немає ініціалізованої змінної, немає умови, тому цикл працюватиме вічно – нескінченний цикл.
Ми також можемо опустити ряд блоків:
int i = 1;
for (; i<4;)
{
Console.WriteLine($"i = {i}");
}
Цей приклад по суті еквівалентний першому прикладу: у нас також є змінна-лічильник, тільки визначена вона поза циклом. Ми маємо умову виконання циклу. І є збільшення змінної вже в самому блоці for.
Також варто зазначити, що можна визначати кілька змінних в оголошенні циклу:
for (int i = 1, j = 1; i < 10; i++, j++)
Console.WriteLine($"{i*j}");
Тут у першій частині оголошення циклу визначаються дві змінні: i та j. Цикл виконується, поки i не дорівнюватиме 10. Після кожної ітерації змінні i і j збільшуються на одиницю. Консольний висновок програми:
У циклі do спочатку виконується код циклу, потім відбувається перевірка умови в інструкції while. І поки ця умова є істинною, цикл повторюється.
do
{
дії циклу
}
while (умова)
Наприклад:
int i = 6;
do
{
Console.WriteLine(i);
i--;
}
while (i > 0);
Тут код циклу спрацює 6 разів, доки i не стане рівним нулю. Але важливо відзначити, що цикл do гарантує хоча б одноразове виконання дій, навіть якщо умова в інструкції while не буде істинною. Тобто ми можемо написати:
int i = -1;
do
{
Console.WriteLine(i);
i--;
}
while (i > 0);
Хоча у нас змінна i менше 0, цикл все одно один раз виконається.
Цикл while
На відміну від циклу do цикл while відразу перевіряє істинність деякої умови, і якщо умова істинна, то код циклу виконується:
while (умова)
{
дії циклу
}
Наприклад:
int i = 6;
while (i > 0)
{
Console.WriteLine(i);
i--;
}
Цикл foreach призначений для вибору набору або колекції елементів. Його загальне визначення:
foreach(тип_даних змінна in колекція)
{
// дії циклу
}
Після оператора foreach у дужках спочатку йде визначення змінної. Потім ключове слово in і далі колекція, елементи якої потрібно перебрати.
При виконанні цикл послідовно перебирає елементи колекції і поміщає їх у змінну, і в блоці циклу ми можемо виконати з ними деякі дії.
Наприклад, візьмемо рядок. Рядок по суті – це колекція символів. І .NET дозволяє перебрати всі елементи рядка - його символи за допомогою циклу foreach.
foreach(char c in "Tom")
{
Console.WriteLine(c);
}
Тут цикл foreach пробігається по всіх символах рядка "Tom" і кожен символ поміщає символьну змінну c. У блоці циклу значення змінної c виводиться на консоль. Оскільки в рядку "Tom" три символи, цикл виконається три рази. Консольний висновок програми:
T
o
m
Варто зазначити, що обумовлена в оголошенні циклу повинна за типом відповідати типу елементів колекції, що перебирається. Так, елементи рядка – значення типу char – символи. Тому змінна c має тип char. Проте насправді який завжди буває очевидно, який тип представляють елементи колекції. У цьому випадку ми можемо визначити змінну за допомогою оператора var:
foreach(var c in "Tom")
{
Console.WriteLine(c);
}
Іноді виникає ситуація, коли потрібно вийти з циклу, не чекаючи на його завершення. І тут ми можемо скористатися оператором break.
Наприклад:
for (int i = 0; i < 9; i++)
{
if (i == 5)
break;
Console.WriteLine(i);
}
Хоча за умови циклу сказано, що цикл виконуватиметься, доки лічильник i не досягне значення 9, насправді цикл спрацює 5 разів. Так як при досягненні лічильником i значення 5 спрацює оператор break, і цикл завершиться.
Тепер поставимо собі інше завдання. А якщо ми хочемо, щоб під час перевірки цикл не завершувався, а просто пропускав поточну ітерацію. Для цього ми можемо скористатися оператором continue:
for (int i = 0; i < 9; i++)
{
if (i == 5)
continue;
Console.WriteLine(i);
}
У цьому випадку цикл, коли дійде до числа 5, яке не задовольняє умову перевірки, просто пропустить це число та перейде до наступної ітерації:
Варто зазначити, що оператори break і continue можна використовувати у будь-якому типі циклів.
Вкладені цикли
Одні цикли можуть бути вкладені в інші. Наприклад:
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
Console.Write($"{i*j}\t");
}
Console.WriteLine();
}
У разі цикл for (int i = 1; i < 10; i++) виконується 9 разів, тобто має 9 ітерацій. Але у межах кожної ітерації виконується дев'ять разів вкладений цикл for (int j = 1; j < 10; j++). У результаті програма виведе таблицю множення.
Створити масив
Масиви використовуються для зберігання кількох значень в одній змінній замість оголошення окремих змінних кожного значення.
Щоб оголосити масив, визначте тип змінної за допомогою квадратних дужок:
string[] cars;
Тепер ми оголосили змінну, яка містить масив рядків.
Щоб вставити в нього значення, ми можемо використовувати літерал масиву - помістіть значення у список, розділений комами, усередині фігурних дужок.
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
Щоб створити масив цілих чисел, ви можете написати:
int[] myNum = {10, 20, 30, 40};
Доступ до елементів масиву
Ви отримуєте доступ до елемента масиву, звертаючись до номера індексу.
Цей оператор отримує доступ до значення першого елемента cars:
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
Console.WriteLine(cars[0]);
Примітка. Індекси масиву починаються з 0: [0] перший елемент. [1] - Другий елемент і т. д.
Змінити елемент масиву
Щоб змінити значення певного елемента, зверніться до номера індексу:
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
cars[0] = "Opel";
Console.WriteLine(cars[0]);
Довжина масиву
Щоб дізнатися, скільки елементів має масив, використовуйте властивість Length:
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
Console.WriteLine(cars.Length);
Перебрати масив
Ви можете перебирати елементи масиву за допомогою циклу for і використовувати властивість Length, щоб вказати скільки разів повинен виконуватися цикл.
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
for (int i = 0; i < cars.Length; i++)
{
Console.WriteLine(cars[i]);
}
Цикл foreach
Існує також цикл foreach, який використовується виключно для перебору елементів у масиві:
foreach (type variableName in arrayName)
{
// code block to be executed
}
У наступному прикладі всі елементи масиву cars виводяться за допомогою циклу foreach:
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
foreach (string і in cars)
{
Console.WriteLine(i);
}
Наведений вище приклад можна прочитати так: для кожного елемента рядка (позначеного i як в індексі) в cars виведіть значення i.
Якщо ви порівняєте цикл for і цикл foreach, то побачите, що метод foreach легше написати, він вимагає лічильника (використовується властивість Length) і зручніший для читання.
Сортування масивів
Доступно безліч методів роботи з масивами, наприклад Sort(), який сортує масив в алфавітному або зростаючому порядку:
// Sort a string
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
Array.Sort(cars);
foreach (string i in cars)
{
Console.WriteLine(i);
}
// Sort an int
int[] myNumbers = {5, 1, 8, 9};
Array.Sort(myNumbers);
foreach (int i in myNumbers)
{
Console.WriteLine(i);
}
Простір імен System.Linq
Інші корисні методи масиву, такі як Min, Max та Sum, можна знайти у просторі імен System.Linq:
using System;
using System.Linq;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
int[] myNumbers = {5, 1, 8, 9};
Console.WriteLine(myNumbers.Max()); // returns the largest value
Console.WriteLine(myNumbers.Min()); // returns the smallest value
Console.WriteLine(myNumbers.Sum()); // returns the sum of elements
}
}
}
Інші способи створення масиву
У C# існують різні способи створення масиву:
// Create an array of four elements, and add values later
string[] cars = new string[4];
// Create an array of four elements and add values right away
string[] cars = new string[4] {"Volvo", "BMW", "Ford", "Mazda"};
// Create an array of four elements without specifying the size
string[] cars = new string[] {"Volvo", "BMW", "Ford", "Mazda"};
// Create an array of four elements, omitting the new keyword, and without specifying the size
string[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
Вам вирішувати, який варіант ви оберете. У цих уроках ми часто використовуватимемо останній варіант, тому що він швидше і легше читається.
Однак ви повинні зазначити, що якщо ви оголошуєте масив та ініціалізуєте його пізніше, ви повинні використовувати нове ключове слово:
// Declare an array
string[] cars;
// Add values, using new
cars = new string[] {"Volvo", "BMW", "Ford"};
// Add values without using new (this will cause an error)
cars = {"Volvo", "BMW", "Ford"};
Метод — це блок коду, який запускається лише за виклику.
Ви можете передавати дані, відомі як параметри, метод.
Методи використовуються для виконання певних дій і вони також відомі як функції.
Навіщо використати методи? Для повторного використання коду: визначте код один раз і використовуйте його багато разів.
Створитиметод
Метод визначається ім'ям методу, за яким йдуть круглі дужки (). C# надає деякі визначені методи, з якими ви вже знайомі, такі як Main(), але ви також можете створювати власні методи для виконання певних дій:
class Program
{
static void MyMethod()
{
// code to be executed
}
}
Пояснення прикладу
MyMethod() - це ім'я методу
static означає, що метод належить класу Program, а чи не об'єкту класу Program.
void означає, що цей метод не має значення, що повертається. Ви дізнаєтеся більше про значення, що повертаються пізніше в цьому розділі.
Примітка. У C# рекомендується починати імена методів із великої літери, оскільки це полегшує читання коду.
Виклик метода
Щоб викликати (виконати) метод, напишіть ім'я методу, за яким слідують дві круглі дужки () та крапка з комою;
У прикладі MyMethod() використовується для друку тексту (дії) при його викликі:
static void MyMethod()
{
Console.WriteLine("I just got executed!");
}
static void Main(string[] args)
{
MyMethod();
}
// Outputs "I just got executed!"
Метод можна викликати кілька разів:
static void MyMethod()
{
Console.WriteLine("I am learning programming");
}
static void Main(string[] args)
{
MyMethod();
MyMethod();
MyMethod();
}
Параметри та аргументи
Інформація може бути передана методам як параметр. Параметри діють як змінні всередині методу.
Вони вказуються після імені методу у круглих дужках. Ви можете додати стільки параметрів, скільки хочете, просто розділіть їх комою.
У наступному прикладі є метод, який приймає рядок з ім'ям fname як параметр. При викликі методу ми передаємо ім'я, яке використовується всередині методу для повного імені:
static void MyMethod(string fname)
{
Console.WriteLine(fname + " Refsnes");
}
static void Main(string[] args)
{
MyMethod("Liam");
MyMethod("Jenny");
MyMethod("Anja");
}
Коли параметр передається методу, він називається аргументом. Отже, з прикладу вище: fname – це параметр, а Liam, Jenny та Anja – аргументи.
Значення параметра за замовчуванням
Ви також можете використовувати значення за промовчанням, використовуючи знак рівності (=). Якщо ми викликаємо метод без аргументу, він використовує значення за замовчуванням (Норвегія):
static void MyMethod(string country = "Norway")
{
Console.WriteLine(country);
}
static void Main(string[] args)
{
MyMethod("Sweden");
MyMethod("India");
MyMethod();
MyMethod("USA");
}
Параметр за замовчуванням часто називають «необов'язковим параметром». У цьому прикладі країна є необов'язковим параметром, а «Норвегія» — значенням за промовчанням.
Декілька параметрів
Ви можете мати стільки параметрів, скільки хочете:
static void MyMethod(string fname, int age)
{
Console.WriteLine(fname + " is " + age);
}
static void Main(string[] args)
{
MyMethod("Liam", 5);
MyMethod("Jenny", 8);
MyMethod("Anja", 31);
}
Зверніть увагу, що під час роботи з кількома параметрами виклик методу повинен мати таку ж кількість аргументів, як і параметрів, і аргументи повинні передаватися у тому порядку.
Значення, що повертаються
Ключове слово void, яке використовується в наведених вище прикладах, вказує, що метод не повинен повертати значення. Якщо ви хочете, щоб метод повертав значення, ви можете використовувати примітивний тип даних (наприклад, int або double) замість void та використовувати ключове слово return всередині методу:
static int MyMethod(int x)
{
return 5 + x;
}
static void Main(string[] args)
{
Console.WriteLine(MyMethod(3));
}
У цьому прикладі повертається сума двох параметрів методу:
static int MyMethod(int x, int y)
{
return x + y;
}
static void Main(string[] args)
{
Console.WriteLine(MyMethod(5, 3));
}
Ви також можете зберегти результат у змінній (рекомендується, оскільки її легше читати та підтримувати):
static int MyMethod(int x, int y)
{
return x + y;
}
static void Main(string[] args)
{
int z = MyMethod(5, 3);
Console.WriteLine(z);
}
Іменовані аргументи
Можна також надсилати аргументи за допомогою синтаксису ключ: значення.
Таким чином, порядок аргументів не має значення:
static void MyMethod(string child1, string child2, string child3)
{
Console.WriteLine("The youngest child is: " + child3);
}
static void Main(string[] args)
{
MyMethod(child3: "John", child1: "Liam", child2: "Liam");
}
При перевантаженні методів кілька методів можуть мати однакові назви з різними параметрами:
int MyMethod(int x)
float MyMethod(float x)
double MyMethod(double x, double y)
Розглянемо наступний приклад, у якому є два методи додавання чисел різного типу:
static int PlusMethodInt(int x, int y)
{
return x + y;
}
static double PlusMethodDouble(double x, double y)
{
return x + y;
}
static void Main(string[] args)
{
int myNum1 = PlusMethodInt(8, 5);
double myNum2 = PlusMethodDouble(4.3, 6.26);
Console.WriteLine("Int: " + myNum1);
Console.WriteLine("Double: " + myNum2);
}
Замість визначення двох методів, які повинні робити те саме, краще перевантажити один.
У наведеному нижче прикладі ми перевантажуємо метод PlusMethod для роботи як для int, так і для double:
static int PlusMethod(int x, int y)
{
return x + y;
}
static double PlusMethod(double x, double y)
{
return x + y;
}
static void Main(string[] args)
{
int myNum1 = PlusMethod(8, 5);
double myNum2 = PlusMethod(4.3, 6.26);
Console.WriteLine("Int: " + myNum1);
Console.WriteLine("Double: " + myNum2);
}
Примітка. Кілька методів можуть мати однакові назви, якщо кількість і/або тип параметрів відрізняються.
ООП означає об'єктно-орієнтоване програмування.
Процедурне програмування — це написання процедур або методів, які виконують операції над даними, тоді як об’єктно-орієнтоване програмування — це створення об’єктів, які містять як дані, так і методи.
Об'єктно-орієнтоване програмування має кілька переваг перед процедурним:
ООП швидший і легший у виконанні
ООП забезпечує чітку структуру для програм
ООП допомагає зберегти код C# СУХИМ (не повторюйте себе) і полегшує підтримку, зміну та налагодження коду
ООП дає змогу створювати повністю багаторазові програми з меншим кодом і коротшим часом розробки
Порада. Принцип «Не повторюйся» (DRY) спрямований на зменшення повторення коду. Ви повинні вилучити коди, які є загальними для програми, розмістити їх в одному місці та повторно використовувати замість повторення.
C# - Що таке класи та об'єкти?
Класи та об'єкти є двома основними аспектами об'єктно-орієнтованого програмування.
Подивіться на наступну ілюстрацію, щоб побачити різницю між класом і об’єктами:
Отже, клас — це шаблон для об’єктів, а об’єкт — це екземпляр класу.
Коли окремі об’єкти створюються, вони успадковують усі змінні та методи класу.
У наступному розділі ви дізнаєтесь набагато більше про класи та об’єкти.
З попереднього розділу ви дізналися, що C# є об’єктно-орієнтованою мовою програмування.
Усе в C# пов’язане з класами та об’єктами разом із його атрибутами та методами. Наприклад: у реальному житті автомобіль є предметом. Автомобіль має атрибути, такі як вага та колір, і методи, такі як водіння та гальмування.
Клас схожий на конструктор об’єктів або «схему» для створення об’єктів.
Щоб створити клас, використовуйте ключове слово class:
class Car
{
string color = "red";
}
Коли змінна оголошується безпосередньо в класі, її часто називають полем (або атрибутом).
Це не обов’язково, але бажано починати з великої літери під час іменування класів. Крім того, часто ім’я файлу C# і клас збігаються, оскільки це робить наш код організованим. Однак це не обов’язково (як у Java).
class Car
{
string color = "red";
static void Main(string[] args)
{
Car myObj = new Car();
Console.WriteLine(myObj.color);
}
}
Зауважте, що ми використовуємо крапковий синтаксис (.) для доступу до змінних/полів усередині класу (myObj.color). Ви дізнаєтеся більше про поля в наступному розділі.
Ви можете створити кілька об'єктів одного класу:
class Car
{
string color = "red";
static void Main(string[] args)
{
Car myObj1 = new Car();
Car myObj2 = new Car();
Console.WriteLine(myObj1.color);
Console.WriteLine(myObj2.color);
}
}
Використання кількох класів
Ви також можете створити об’єкт класу та отримати доступ до нього в іншому класі. Це часто використовується для кращої організації класів (один клас містить усі поля та методи, тоді як інший клас містить метод Main() (код, який потрібно виконати)).
prog2.cs
prog.cs
prog2.cs
class Car
{
public string color = "red";
}
prog.cs
class Program
{
static void Main(string[] args)
{
Car myObj = new Car();
Console.WriteLine(myObj.color);
}
}