Українська
Символи, рядки, змінні та null
Логічний, символьний і рядковий типи
Логічний тип bool має два значення: true і false. Його отримують операції порівняння, а використовують в умовах. На відміну від C і C++, у C# число не можна використати як логічне значення: bool flag = 1; спричиняє помилку CS0029.
Символьний тип char зберігає один символ Юнікоду в кодуванні UTF-16 і займає 2 байти. Символьні літерали записують в одинарних лапках: 'A', 'ї', '7'. Спеціальні символи задають керувальними послідовностями (escape sequences) (табл. 2.3).
Таблиця 2.3. Керувальні послідовності
| Запис | Символ | Запис | Символ |
|---|---|---|---|
\n | новий рядок | \' | одинарна лапка |
\t | табуляція | \" | подвійна лапка |
\\ | зворотна скісна риска | \0 | символ із кодом 0 |
\r | повернення каретки | \u0410 | символ Юнікоду за кодом (кирилична А) |
Символ має числовий код, тому з ним можна виконувати арифметичні операції, але результат має тип int:
cs
char letter = 'A';
Console.WriteLine(letter + 1); // 66
Console.WriteLine((char)(letter + 1)); // B
Console.WriteLine('7' - '0'); // 7 – цифра як число
Console.WriteLine(char.IsDigit('7')); // True
Console.WriteLine(char.ToUpper('ї')); // ЇРядковий тип string – послідовність символів char. Це посилальний тип, але з двома особливостями: рядки незмінні (immutable) – будь-яка «зміна» створює новий рядок, а операція == порівнює вміст рядків, а не посилання. Рядки детально розглядаються в темі 4.
cs
string s = "Hello";
string t = s;
t += "!"; // створено новий рядок
Console.WriteLine(s); // Hello
Console.WriteLine(t); // Hello!
Console.WriteLine(s.Length); // 5Тип object може зберігати значення будь-якого типу. Він корисний, коли тип заздалегідь невідомий, але втрачає переваги статичної типізації: щоб знову виконувати операції над значенням, його потрібно явно привести до потрібного типу.
Змінні та константи
Змінна (variable) – іменована ділянка пам’яті, що зберігає значення певного типу. Змінну оголошують, вказуючи тип та ім’я, і, як правило, одразу ініціалізують – задають початкове значення:
cs
int count = 10;
double price = 12.5, discount = 0.1; // дві змінні одного типу
string city; // оголошення без значення
city = "Мадрид"; // присвоюванняЛокальну змінну не можна використати, доки їй не присвоєно значення: компілятор повідомить про помилку CS0165 Use of unassigned local variable. Змінну можна змінювати, але лише значеннями її типу.
Область видимості (scope) локальної змінної – від місця оголошення до кінця блоку { … }, у якому її оголошено. У вкладеному блоці не можна оголосити змінну з тим самим ім’ям (помилка CS0136).
Правила іменування. Ім’я складається з літер, цифр і символу _, не може починатися з цифри та збігатися з ключовим словом. Регістр літер має значення: count і Count – різні імена. За угодами .NET локальні змінні називають у стилі camelCase (totalPrice), а константи – у стилі PascalCase (MaxCount). Назви мають пояснювати зміст: distanceKm краще, ніж d. Хоча C# дозволяє українські літери в іменах, прийнято використовувати англійські слова (https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/identifier-names).
Неявна типізація var
Замість типу можна записати ключове слово var: тоді компілятор визначає тип змінної за виразом ініціалізації. Змінна все одно має конкретний тип, який не змінюється (рис. 2.5):
cs
var count = 5; // int
var price = 12.5; // double
var sum = 12.5m; // decimal
var big = 5L; // long
var name = "Олена"; // string
var total = price * count; // double
Рис. 2.5. Тип змінної var у підказці Quick Info
Змінна var обов’язково ініціалізується (помилка CS0818), і їй не можна присвоїти null (CS0815). Використовуйте var, коли тип очевидний із правої частини; якщо тип не очевидний, наприклад var result = Calculate();, краще записати його явно.
Константи
Константа (constant) – іменоване значення, яке задається під час компіляції і не змінюється. Її оголошують ключовим словом const:
cs
const double G = 9.81; // прискорення вільного падіння
const int SecondsPerHour = 60 * 60; // обчислюється компілятором
const string Currency = "грн";Значення константи має бути відоме компілятору: число, рядок, логічне значення або вираз із них. Виклик методу, наприклад const double Root = Math.Sqrt(2);, спричиняє помилку CS0133. Константи замінюють «магічні числа» в коді: total * VatRate зрозуміліше, ніж total * 0.2m, а змінити ставку потрібно лише в одному місці.
Значення за замовчуванням
Кожен тип має значення за замовчуванням (default value), яке отримують поля класів та елементи масивів без явної ініціалізації: 0 для числових типів, false для bool, '\0' для char, null для посилальних типів. Його повертає вираз default(T) або літерал default:
cs
int zero = default; // 0
bool flag = default(bool); // False
string? text = default; // nullТипи з можливістю значення null
Значення null означає «немає значення» або «посилання нікуди не вказує». Тип-значення, наприклад int, завжди містить число, тому для випадків, коли значення може бути відсутнім (необов’язкове поле форми, невідома оцінка), використовують тип-значення з можливістю null (nullable value type): int?, double?, bool?.
cs
int? age = null;
Console.WriteLine(age.HasValue); // False
Console.WriteLine(age.GetValueOrDefault()); // 0
Console.WriteLine(age + 1 == null); // True
age = 19;
Console.WriteLine(age.Value); // 19Властивість HasValue показує, чи є значення, а Value повертає його; якщо значення немає, звернення до Value спричиняє виняток InvalidOperationException. Арифметична операція з null дає null (https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/nullable-value-types).
Операції ?? і ??=
Операція об’єднання з null a ?? b (null-coalescing operator) повертає a, якщо воно не null, інакше – b. Операція a ??= b присвоює змінній a значення b, лише якщо a дорівнює null (https://learn.microsoft.com/dotnet/csharp/language-reference/operators/null-coalescing-operator):
cs
int? discount = null;
int percent = discount ?? 0; // 0
string? name = Console.ReadLine();
name ??= "Гість"; // якщо введення завершено
string input = Console.ReadLine() ?? "";Посилальні типи з можливістю null
Посилальні змінні завжди могли містити null, а звернення до члена через null (name.Length) спричиняє найпоширеніший виняток NullReferenceException. Щоб знаходити такі помилки під час компіляції, у C# є контекст допустимості null (nullable reference types). У нових проєктах його вмикає рядок <Nullable>enable</Nullable> у файлі .csproj. У цьому контексті:
string– рядок, який не повинен бутиnull;string?– рядок, який може бутиnull, наприклад результатConsole.ReadLine().
Компілятор аналізує код і видає попередження (не помилки) (рис. 2.6):
cs
string name = Console.ReadLine(); // CS8600
string? city = Console.ReadLine();
Console.WriteLine(city.Length); // CS8602Попередження CS8600 означає, що значення, яке може бути null, присвоюється змінній типу без ?, а CS8602 – що змінну, яка може бути null, розіменовано без перевірки. Виправлення: підставити значення за замовчуванням операцією ?? або перевірити змінну на null. Такі попередження не можна ігнорувати: кожне з них вказує на можливий виняток під час виконання. Детально контекст допустимості null розглядається в темі 7 (https://learn.microsoft.com/dotnet/csharp/nullable-references).

Рис. 2.6. Попередження про можливе значення null