C# (вимовляється як «See Sharp») — сучасна, об’єктно-орієнтована та безпечна для типів мова програмування. C# дозволяє розробникам створювати багато типів безпечних і надійних програм, які працюють у .NET. C# бере свій початок у сімействі мов C і буде негайно знайомий програмістам C, C++, Java та JavaScript. У цьому огляді представлено огляд основних компонентів мови C# 11 і попередніх версій. Якщо ви хочете вивчити мову на інтерактивних прикладах, спробуйте вступ до підручників C# .
C# — об’єктно-орієнтована, компонентно-орієнтована мова програмування. C# надає мовні конструкції для безпосередньої підтримки цих концепцій, що робить C# природною мовою для створення та використання програмних компонентів. З моменту свого створення C# додав функції для підтримки нових робочих навантажень і новітніх практик проектування програмного забезпечення. За своєю суттю C# є об’єктно-орієнтованою мовою. Ви визначаєте типи та їх поведінку.
Кілька функцій C# допомагають створювати надійні та довговічні програми. Збирання сміття автоматично звільняє пам’ять, зайняту недоступними невикористаними об’єктами. Типи, що допускають значення Nullable, захищають від змінних, які не посилаються на виділені об’єкти. Обробка винятків забезпечує структурований і розширюваний підхід до виявлення та відновлення помилок. Лямбда-вирази підтримують методи функціонального програмування. Синтаксис Language Integrated Query (LINQ) створює загальний шаблон для роботи з даними з будь-якого джерела. Підтримка мови для асинхронних операцій забезпечує синтаксис для побудови розподілених систем. C# має уніфіковану систему типів. Усі типи C#, включаючи примітивні типи, такі як int
і double
, успадковуються від одного кореневого object
типу. Усі типи мають спільний набір спільних операцій. Цінності будь-якого типу можна зберігати, транспортувати та працювати з ними узгоджено. Крім того, C# підтримує як визначені користувачем типи посилань , так і типи значень . C# дозволяє динамічно розміщувати об’єкти та вбудоване зберігання легких структур. C# підтримує загальні методи та типи, що забезпечує підвищену безпеку типів і продуктивність. C# надає ітератори, які дозволяють розробникам класів колекцій визначати користувальницьку поведінку для клієнтського коду.
C# наголошує на версії , щоб програми та бібліотеки могли розвиватися з часом сумісним чином. Аспекти дизайну C#, на які безпосередньо вплинули міркування щодо керування версіями, включають окремі модифікатори virtual
та override
правила вирішення перевантаження методів і підтримку явних декларацій членів інтерфейсу.
Архітектура .NET
Програми C# виконуються на .NET, віртуальній системі виконання, що називається загальномовним середовищем виконання (CLR), і наборі бібліотек класів. CLR — це реалізація Microsoft спільної мовної інфраструктури (CLI), міжнародного стандарту. CLI є основою для створення середовищ виконання та розробки, у яких мови та бібліотеки безперебійно працюють разом.
Вихідний код, написаний мовою C#, компілюється в проміжну мову (IL) , яка відповідає специфікації CLI. Код IL і ресурси, такі як растрові зображення та рядки, зберігаються в збірці, зазвичай із розширенням .dll . Збірка містить маніфест, який надає інформацію про типи, версію та культуру збірки.
Коли програма C# виконується, збірка завантажується в CLR. CLR виконує компіляцію Just-In-Time (JIT) для перетворення коду IL у власні машинні інструкції. CLR надає інші служби, пов’язані з автоматичним збиранням сміття, обробкою винятків і керуванням ресурсами. Код, який виконує CLR, іноді називають «керованим кодом». «Некерований код» компілюється в рідну машинну мову, націлену на певну платформу.
Сумісність мов є ключовою особливістю .NET. Код IL, створений компілятором C#, відповідає специфікації загального типу (CTS). Код IL, згенерований з C#, може взаємодіяти з кодом, який було згенеровано з версій .NET F#, Visual Basic, C++. Існує понад 20 інших CTS-сумісних мов. Одна збірка може містити декілька модулів, написаних різними мовами .NET. Типи можуть посилатися один на одного, як якщо б вони були написані однією мовою.
Окрім служб середовища виконання, .NET також містить великі бібліотеки. Ці бібліотеки підтримують багато різних робочих навантажень. Вони організовані в простори імен, які надають широкий спектр корисних функцій. Бібліотеки включають усе: від введення та виведення файлів до маніпулювання рядками та синтаксичного аналізу XML, інфраструктури веб-додатків до елементів керування Windows Forms. Типова програма на C# широко використовує бібліотеку класів .NET для виконання типових «сантехнічних» робіт.
Щоб отримати додаткові відомості про .NET, див. Огляд .NET .
Привіт Світ
Програма «Hello, World» традиційно використовується для знайомства з мовою програмування. Ось це на C#:
C#Копіябігти
using System;
class Hello
{
static void Main()
{
// This line prints "Hello, World"
Console.WriteLine("Hello, World");
}
}
Програма «Hello, World» починається з директиви using
, яка посилається на System
простір імен. Простори імен забезпечують ієрархічні засоби організації програм і бібліотек C#. Простори імен містять типи та інші простори імен — наприклад, System
простір імен містить кілька типів, таких як Console
клас, на який посилається програма, і багато інших просторів імен, таких як IO
і Collections
. Директива using
, яка посилається на заданий простір імен, дозволяє некваліфіковане використання типів, які є членами цього простору імен. Через using
директиву програма може використовувати Console.WriteLine
як скорочення для System.Console.WriteLine
.
Клас Hello
, оголошений програмою «Hello, World», має єдиного члена — метод під назвою Main
. Метод Main
оголошується з static
модифікатором. Хоча методи екземплярів можуть посилатися на конкретний екземпляр охоплюючого об’єкта за допомогою ключового слова this
, статичні методи працюють без посилання на конкретний об’єкт. Згідно з угодою, статичний метод named Main
служить точкою входу програми C#.
Рядок, що починається з, //
є однорядковим коментарем . Однорядкові коментарі C# починаються з //
продовження до кінця поточного рядка. C# також підтримує багаторядкові коментарі . Багаторядкові коментарі починаються з /*
і закінчуються на */
. Вихід програми виробляється методом WriteLine
класу Console
в System
просторі імен. Цей клас надається стандартними бібліотеками класів, на які за замовчуванням компілятор автоматично посилається.
Ви використовуєте .NET SDK для створення власної програми «Hello, World». Після інсталяції SDK ви запускаєте dotnet new console
, щоб створити базову програму «Hello, World», яку можна змінювати. Щоб отримати додаткові відомості, дивіться підручник Hello, World у розділі .NET Початок роботи.
Типи та змінні
Тип визначає структуру та поведінку будь-яких даних у C# . Оголошення типу може включати його члени, базовий тип, інтерфейси, які він реалізує, та операції, дозволені для цього типу. Змінна — це мітка, яка посилається на екземпляр певного типу.
У C# є два види типів: типи значень і типи посилань . Змінні типів значень безпосередньо містять свої дані. Змінні посилальних типів зберігають посилання на свої дані, останні відомі як об’єкти. За допомогою посилальних типів дві змінні можуть посилатися на один і той же об’єкт, а операції над однією змінною можуть впливати на об’єкт, на який посилається інша змінна. З типами значень кожна змінна має власну копію даних, і неможливо, щоб операції над одним впливали на інші (за винятком змінних параметрів і ) ref
.out
Ідентифікатор – це ім’я змінної. Ідентифікатор — це послідовність символів Unicode без пробілів. Ідентифікатор може бути зарезервованим словом C#, якщо перед ним стоїть @
. Використання зарезервованого слова як ідентифікатора може бути корисним під час взаємодії з іншими мовами.
Типи значень у C# далі поділяються на прості типи , типи enum , типи структур , типи значень із можливістю обнулення та типи значень кортежу . Довідкові типи C# далі поділяються на типи класів , типи інтерфейсів , типи масивів і типи делегатів .
Наступний план містить огляд системи типів C#.
- Типи значень
- Прості типи
- Знаковий інтеграл :
sbyte
,short
,int
,long
- Беззнаковий інтеграл :
byte
,ushort
,uint
,ulong
- Символи Юнікоду :
char
, що представляє одиницю коду UTF-16 - IEEE двійковий з плаваючою комою :
float
,double
- Десяткове число з плаваючою комою високої точності :
decimal
- Boolean:
bool
, що представляє булеві значення — значення, які є абоtrue
абоfalse
- Знаковий інтеграл :
- Типи Enum
- Визначені користувачем типи форми
enum E {...}
. Типenum
— це окремий тип із іменованими константами. Коженenum
тип має базовий тип, який має бути одним із восьми інтегральних типів. Набір значень типуenum
такий самий, як і набір значень базового типу.
- Визначені користувачем типи форми
- Типи структур
- Визначені користувачем типи форми
struct S {...}
- Визначені користувачем типи форми
- Типи значення Nullable
- Розширення всіх інших типів значень зі
null
значенням
- Розширення всіх інших типів значень зі
- Типи значень кортежу
- Визначені користувачем типи форми
(T1, T2, ...)
- Визначені користувачем типи форми
- Прості типи
- Довідкові типи
- Типи класів
- Остаточний базовий клас усіх інших типів:
object
- Рядки Unicode :
string
, які представляють послідовність одиниць коду UTF-16 - Визначені користувачем типи форми
class C {...}
- Остаточний базовий клас усіх інших типів:
- Типи інтерфейсів
- Визначені користувачем типи форми
interface I {...}
- Визначені користувачем типи форми
- Типи масивів
- Одновимірні, багатовимірні та зубчасті. Наприклад:
int[]
,int[,]
, іint[][]
- Одновимірні, багатовимірні та зубчасті. Наприклад:
- Типи делегатів
- Визначені користувачем типи форми
delegate int D(...)
- Визначені користувачем типи форми
- Типи класів
Програми C# використовують оголошення типів для створення нових типів. Оголошення типу вказує назву та члени нового типу. Шість категорій типів C# можуть бути визначені користувачем: типи класів, типи структур, типи інтерфейсів, типи enum, типи делегатів і типи значень кортежу. Ви також можете оголошувати record
типи або record struct
, або record class
. Типи записів мають елементи, синтезовані компілятором. Ви використовуєте записи переважно для зберігання значень із мінімальною пов’язаною поведінкою.
- Тип
class
визначає структуру даних, яка містить елементи даних (поля) і функціональні елементи (методи, властивості та інші). Типи класів підтримують єдине успадкування та поліморфізм, механізми, за допомогою яких похідні класи можуть розширювати та спеціалізувати базові класи. - Тип
struct
схожий на тип класу тим, що він представляє структуру з членами даних і функціональними членами. Однак, на відміну від класів, структури є типами значень і зазвичай не потребують виділення купи. Типи структур не підтримують визначене користувачем успадкування, і всі типи структур неявно успадковують типobject
. - Тип
interface
визначає контракт як іменований набір публічних членів. Aclass
абоstruct
, що реалізує,interface
має забезпечити реалізації членів інтерфейсу. Aninterface
може успадкувати від кількох базових інтерфейсів, аclass
можеstruct
реалізувати декілька інтерфейсів. - Тип
delegate
представляє посилання на методи з певним списком параметрів і типом повернення. Делегати дають змогу розглядати методи як сутності, які можна призначати змінним і передавати як параметри. Делегати аналогічні типам функцій, що надаються функціональними мовами. Вони також подібні до концепції покажчиків на функції, які є в деяких інших мовах. На відміну від покажчиків на функції, делегати є об’єктно-орієнтованими та безпечними для типів.
Усі типи class
, struct
, interface
, і delegate
підтримують генерики, завдяки чому їх можна параметризувати іншими типами.
C# підтримує одновимірні та багатовимірні масиви будь-якого типу. На відміну від перерахованих вище типів, типи масивів не потрібно оголошувати, перш ніж їх можна буде використовувати. Натомість типи масивів створюються за назвою типу в квадратних дужках. Наприклад, int[]
є одновимірним масивом int
, int[,]
є двовимірним масивом int
і int[][]
є одновимірним масивом одновимірних масивів або “зубчастим” масивом int
.
Типи, що допускають значення Nullable, не потребують окремого визначення. Для кожного типу, що не допускає нуль T
, існує відповідний тип T?
, який може містити додаткове значення null
. Наприклад, int?
це тип, який може містити будь-яке 32-розрядне ціле число або значення null
, і string?
є типом, який може містити будь-яке string
або значення null
.
Система типів C# уніфікована таким чином, що значення будь-якого типу можна розглядати як object
. Кожен тип у C# прямо чи опосередковано походить від object
типу класу та object
є основним базовим класом усіх типів. Значення посилальних типів розглядаються як об’єкти, просто переглядаючи значення як тип object
. Значення типів значень розглядаються як об’єкти шляхом виконання операцій упаковки та розпакування . У наступному прикладі значення перетворюється на .int
object
int
C#Копія
int i = 123;
object o = i; // Boxing
int j = (int)o; // Unboxing
Коли значення типу значення присвоюється посиланню object
, для зберігання цього значення виділяється «ящик». Це поле є екземпляром еталонного типу, і значення копіюється в це поле. І навпаки, коли object
посилання приводиться до типу значення, перевіряється, що посилання object
є полем правильного типу значення. Якщо перевірка проходить успішно, значення в полі копіюється до типу значення.
Уніфікована система типів C# фактично означає, що типи значень розглядаються як object
посилання «на вимогу». Завдяки уніфікації бібліотеки загального призначення, які використовують типи, object
можна використовувати з усіма типами, які походять від object
, включаючи як посилальні типи, так і типи значень.
У C# існує кілька типів змінних , включаючи поля, елементи масиву, локальні змінні та параметри. Змінні представляють місця зберігання. Кожна змінна має тип, який визначає, які значення можуть зберігатися в змінній, як показано нижче.
- Тип значення, що не допускає значення NULL
- Значення саме цього типу
- Тип значення Nullable
- Значення
null
або значення саме цього типу
- Значення
- об’єкт
- Посилання
null
, посилання на об’єкт будь-якого типу посилання або посилання на значення в рамці будь-якого типу значення
- Посилання
- Тип класу
- Посилання
null
, посилання на екземпляр цього типу класу або посилання на екземпляр класу, похідного від цього типу класу
- Посилання
- Тип інтерфейсу
- Посилання
null
, посилання на екземпляр типу класу, який реалізує цей тип інтерфейсу, або посилання на значення в коробці типу значення, яке реалізує цей тип інтерфейсу
- Посилання
- Тип масиву
- Посилання
null
, посилання на екземпляр цього типу масиву або посилання на екземпляр сумісного типу масиву
- Посилання
- Тип делегата
- Посилання
null
або посилання на екземпляр сумісного типу делегату
- Посилання
Структура програми
Ключовими організаційними концепціями в C# є програми , простори імен , типи , члени та збірки . Програми оголошують типи, які містять члени та можуть бути організовані в простори імен. Прикладами типів є класи, структури та інтерфейси. Прикладами членів є поля, методи, властивості та події. Коли програми C# компілюються, вони фізично упаковуються в збірки. Збірки зазвичай мають розширення файлу .exe
або .dll
, залежно від того, реалізують вони програми чи бібліотеки відповідно.
Як невеликий приклад розглянемо наведений нижче код C#:
C#Копія
namespace Acme.Collections;
public class Stack<T>
{
Entry _top;
public void Push(T data)
{
_top = new Entry(_top, data);
}
public T Pop()
{
if (_top == null)
{
throw new InvalidOperationException();
}
T result = _top.Data;
_top = _top.Next;
return result;
}
class Entry
{
public Entry Next { get; set; }
public T Data { get; set; }
public Entry(Entry next, T data)
{
Next = next;
Data = data;
}
}
}
Повна назва цього класу – Acme.Collections.Stack
. Клас містить кілька членів: поле з іменем _top
, два методи з іменами Push
та Pop
та вкладений клас з іменем Entry
. Крім того, клас Entry
містить три члени: властивість під назвою Next
, властивість під назвою Data
та конструктор. Це Stack
загальний клас . Він має один параметр типу, T
який замінюється на конкретний тип, коли він використовується.
Стек — це колекція “першим прийшов – останнім вийшов” (FILO). Нові елементи додаються до вершини стека. Коли елемент видаляється, він видаляється з вершини стека. У попередньому прикладі оголошено Stack
тип, який визначає сховище та поведінку для стека. Ви можете оголосити змінну, яка посилається на екземпляр типу Stack
, щоб використовувати цю функціональність.
Збірки містять виконуваний код у формі інструкцій проміжної мови (IL) і символьну інформацію у формі метаданих. Перед виконанням компілятор Just-In-Time (JIT) .NET Common Language Runtime перетворює код IL у збірці на код, специфічний для процесора.
Оскільки збірка є самоописовою одиницею функціональності, яка містить як код, так і метадані, #include
у C# немає потреби в директивах і файлах заголовків. Загальнодоступні типи та члени, що містяться в певній збірці, стають доступними в програмі на C# просто шляхом посилання на цю збірку під час компіляції програми. Наприклад, ця програма використовує Acme.Collections.Stack
клас зі acme.dll
збірки:
C#Копія
class Example
{
public static void Main()
{
var s = new Acme.Collections.Stack<int>();
s.Push(1); // stack contains 1
s.Push(10); // stack contains 1, 10
s.Push(100); // stack contains 1, 10, 100
Console.WriteLine(s.Pop()); // stack contains 1, 10
Console.WriteLine(s.Pop()); // stack contains 1
Console.WriteLine(s.Pop()); // stack is empty
}
}
Щоб скомпілювати цю програму, вам потрібно буде посилатися на збірку, яка містить клас стека, визначений у попередньому прикладі.
Програми C# можна зберігати в кількох вихідних файлах. Під час компіляції програми на C# всі вихідні файли обробляються разом, і вихідні файли можуть вільно посилатися один на одного. Концептуально це виглядає так, ніби всі вихідні файли були об’єднані в один великий файл перед обробкою. Форвардні оголошення ніколи не потрібні в C#, оскільки, за деякими винятками, порядок оголошень незначний. C# не обмежує вихідний файл оголошенням лише одного відкритого типу, а також не вимагає, щоб ім’я вихідного файлу збігалося з типом, оголошеним у вихідному файлі.
Подальші статті цього туру пояснюють ці організаційні блоки.