субота, 1 вересня 2012 р.

C#. Концепція та синтаксис.Частина 2


ОСНОВИ C# Проста програма

Розглянемо код:

using System;
public class MyConsoleWrite { public static int Main() {
Console.WriteLine("Цe є моя C#-
програма!"); return 0;
}
}

Цей код можна записати в текстовий файл MyCSharp. cs та скомпілювати з допомогою компілятора C# (програма csc.exe): csc.exe MyCSharp.cs.
У C# кожен оператор закінчується символом"; ".
Для об'єднання операторів у блоки використовують фігурні дужки: {...}.
Текст, розташований між наборами символів /* та */, є коментарем і компілятором ігнорується. Текст, розташований після символів // і до кінця стрічки, також є коментарем.
Весь код програми повинен міститися в класі або в іншому означенні типу. Класи (та інші типи) на платформі .NET організовуються у простори імен (namespaces). У цьому прикладі простір імен не зазначено, отож клас належить неіменованому загальному простору імен.
Директива using дає вказівку компілятору, що неописані в поточному просторі імен класи потрібно шукати в поданому списку просторів імен.
Кожен виконуваний файл C# повинен мати точку входу - метод Main. Цей метод може не повертати результат (тип void), або повертати ціле число (тип int). Означення методів у C# таке:
[модифікатори] тип_результату НазваМетоду
( [параметри])
{
// тіло методу
}
Тут квадратні дужки позначають необов'язкові елементи.
Модифікатори використовують для встановлення рівня доступу до методу.
C# підтримує загальну систему типів CTS. Кожен тип CTS є класом і володіє методами, корисними для форматування, серіальності та перетворення типів.
Дані програми зберігаються у стеку.
Стек зберігає дані фіксованої довжини, наприклад, цілі значення. Якщо деяка функція A активізує функцію B, то всі змінні, які є локальними щодо функції A, зберігаються у стеку. Після виконання коду функції B керування повертається функції A. У цьому випадку зі стека зчитуються збережені значення локальних змінних.
Дані змінної довжини зберігаються в динамічно розподіленій пам' яті (heap allocation). Динамічну пам' ять використовують також для збереження даних, тривалість життя яких повинна бути довшою за тривалість життя методу, у якому їх означено.
C# ділить свої типи даних на дві категорії залежно від місця зберігання. Змінні типів за значенням зберігають свої дані в стеку, а змінні типів за посиланням - в динамічній пам'яті.
Операція присвоєння одній змінній за значенням іншої змінної за значенням утворює дві різні копії одних і тих же даних у стеку.
Операція присвоєння одній змінній за посиланням іншої змінної за посиланням спричинює виникнення двох посилань на одну й ту ж ділянку пам' яті, тобто реально дані не дублюються.
У C# базові типи даних, такі, як bool і long, є типами за значенням. Здебільшого складні типи C#, у тім числі й класи, означені користувачем, є типами за посиланням.
Зауважимо, що на відміну від C++, де тип struct є специфічним класом, у C# тип struct є типом за значенням.
У C# ціле число можна оголосити з використанням типу
CTS:
System.Int32 x;
Однак це виглядає неприродно для програміста C. Тому у C# означені псевдоніми (aliases) типів CTS.
C# має 15 базових типів: 13 типів за значенням та 2 типи (string та object) за посиланням.
C# вимагає, щоб кожна змінна за значенням була явно ініціалізована початковим значенням до того, як її використовуватимуть в операціях.
Наступна таблиця містить перелік типів за значенням.
Тип C# Тип CTS                                 Розмір (байт) Кількість точних розрядів
Цілі типи



Sbyte
System.SByte
1

Short
System.Int16
2

Int
System.Int32
4

Long
System.Int64
8

Byte
System.Byte
1

Ushort
System.UInt16
2

Uint
System.UInt32
4

Ulong
System.UInt64
8

Числа з плаваючою крапкою


Float
System.Single
4
7
Double
System.Double
8
15-16
Десятковий тип


Decimal
System.Decimal
16
18
Логічний тип


Bool
System.Boolean
1

Символьний
тип


Char
System.Char
2


Змінним цілого типу можна присвоювати значення у десятковій та шістнадцятковій системах числення. Остання вимагає префікс 0x:
long x = 0x1ab;
Можна використовувати явно типізовані значення:
uint ui = 12U;
long l = 12L;
ulong ul = 12UL;
double f = 1.2F;
decimal d = 1.20M;
Десятковий тип decimal призначений для забезпечення високої точності фінансових операцій.
Змінні логічного типу можуть набувати лише значення false або true.
Значення змінних символьного типу - це символи Unicode. У коді символи розташовують між одинарними лапками. Наприклад: 'a', 'c', '\u0041', '\x0041'. Останні два значення - це символи, задані своїми номерами. Передбачено також зведення типів: (char) 65.
Існують також спеціальні символи:
\' - одинарна лапка                       \f - подання сторінки
\" - подвійна лапка                       \n - нова стрічка
\\ - зворотний слеш                      \r - повернення каретки
\o - null-значення                         \t - символ табуляції
\e - увага                                   \v - вертикальна табуляція \b - повернення назад на 1 символ
Нехай існує деякий клас myClass. Розглянемо стрічку коду
myClass objMyClass;
Ця стрічка формує посилання (тобто резервує sizeof (int) байт для розташування адреси) на ще не утворений об' єкт
objMyClass. Посилання objMyClass матиме значення null.
У C# утворення екземпляра об' єкта за посиланням вимагає ключового слова new:
objMyClass = new myClass();
Цей код утворює об'єкт у динамічній пам'яті та його адресу записує в objMyClass.
C# містить два базових типи за посиланням:
    object (тип CTS System.Object) - кореневий тип, який успадковують усі інші типи CTS (у тім числі типи за значенням);
     string (тип CTS System. String) - стрічка символів Unicode.
У C# тип object є стартовим типом-предком, від якого беруть початок усі внутрішні та всі визначені користувачем типи. Цей тип реалізує низку базових універсальних методів: Equals () , GetHashCode(), GetType(), ToString() та інші. Класам користувача, можливо, доведеться замінити реалізації деяких із цих методів, використовуючи об'єктно-орієнтований принцип перекриття (overriding).
При оголошенні змінної за посиланням типу object або похідного від object класу цій змінній початково надається значення null (за умови, що ця змінна є частиною класу). Якщо ж неініціалізована змінна оголошена в межах методу, у програмі виникне помилка на етапі компіляції.
Об'єкт string дає змогу зберігати (в динамічній пам'яті) набір символів Unicode. Зауважимо, що коли одну стрічкову змінну присвоїти іншій, то в результаті одержимо два посилання на одну й ту ж стрічку в пам'яті. Якщо ж подальший код вносить зміни в одну із цих стрічок, то утворюється новий об'єкт string, водночас інша стрічка залишається без змін.
Стрічкові літерали розташовуються у подвійних лапках "...". Стрічки C# можуть містити ті ж символи, що й тип char. Символ „\", якщо він не призначений для означення спеціального символу, подвоюється:
string filepath = "C:\\Program Files\\F.cs";
Стрічковому літералу може передувати символ @, який дає вказівку всі символи трактувати за принципом „як є":
string filepath = @"The file
C:\Program Files\F.cs is C#-file";
Значення цієї стрічки містить також і всі пробіли перед C:\ .

Складні типи

Структури
Структура - це подібний до класу тип даних за значенням. Оскільки структура розташовується в стеку, вона утворюється більш ефективно, ніж клас. До того ж копіюється простим присвоєнням.
Структура ініціалізується відразу після свого оголошення, а всі поля встановлюються у значення за замовчуванням (0, false, null). Однак компілятор не дає змоги копіювати одну структуру в іншу до її ініціалізації за допомогою ключового слова new.
Приклад:
public struct Student { public string FirstName; public string LastName; public string Group;
}
Student st1, st2;
st1 = new Student;
st1.FirstName = "Андрій";
st1.LastName = "Адаменко";
st1.Group = "Пма-51";
st2 = st1;
У C# структура може виконувати більшість функцій класу (однак не підтримує наслідування реалізацій). Оскільки екземпляри структур розташовані в стеку, доцільно їх використовувати для представлення невеликих об'єктів. Це одна з причин, за якої їх застосовують для реалізації всіх інших типів даних за значенням у платформі .NET.
Переліки
Перелік - це означуваний користувачем цілий тип даних. При оголошенні переліку вказується набір допустимих значень, які можуть набувати екземпляри переліку:
public enum Light {
Green = 0, Yellow = 1, Red = 2
}
Light l;
l = Light.Red;
Переліки мають тип за значенням.
Класи
Класи - це складені типи даних, які містять члени даних (поля, константи та події) і функції (методи, властивості, оператори). Клас є інкапсуляцією даних і функціональних засобів для доступу та роботи із цими даними. Класи можуть також містити вкладені типи даних.
Інтерфейси
Інтерфейси використовують для означення деякої функціональності: властивості, методи, події та індексатори. Інтерфейси не містять самої реалізації цієї функціональності, отож екземпляр інтерфейсу не може бути створений. Якщо кажуть, що клас підтримує деякий інтерфейс, це означає, що в класі є реалізація всіх оголошених інтерфейсом функцій.
Делегати
Делегати - це типи даних, які посилаються на методи. Вони подібні на вказівники функцій в C++, проте передбачають утворення екземпляра класу та активізацію як статичних методів класу, так і методів конкретного екземпляра класу. Делегати дозволяють під час виконання коду визначити, який метод із заданого набору необхідно активізувати.
Масиви
Масив - це колекція змінних однакового типу, звернення до яких відбувається з використанням загального для всіх імені.
Для оголошення одновимірного масиву використовують такий синтаксис:
тип[] ім'я_масиву = new тип[розмір];
Наприклад,
int[] arrInt;
int[] arrInt = new int[10];
Масиви у C# є 0-базованими, тобто перший елемент масиву має індекс 0:
arrInt[0] = 100;
Для встановлення розміру масиву використовують число, константу або змінну. Установити розмір можна також наданням значень елементам масиву при утворенні масиву:
string[] str = new stringHVl-й", "2-й"};
Масиви є класом у C# і володіють певними властивостями та методами. Наприклад,
int L = arrInt.Length; //повертає розмірність масиву
int L = arrInt.GetLength(0); //повертає розмірність
// заданого виміру для багатовимірних масивів
До масивів застосовують статичні методи класу Array. Наприклад, елементи масиву можна сортувати:
Array.Sort (arrInt) ; //сортувати у порядку зростання Array.Reverse(arrInt) ; //змінити напрям сортування.
Багатовимірні масиви
 У C# підтримуються багатовимірні масиви двох типів: прямокутні та ортогональні.
Роботу з прямокутними масивами демонструють такі приклади:
int[,] arr2lnt = new int[5,10]; string[,] studList = { {"Андрій","Банах"},
{"Ірина","Бужська"}, {"Семен","Вовк"}
};
int[,,] arr3lnt = new int[5,10,5]; arr3lnt[0,0,0] = 100;
В ортогональних масивах кожен вимір може мати свою довжину:
int[] [] a = new int[3] []; a[0] = new int [5]; a[1] = new int [3]; a[2] = new int [10];
Типи внутрішніх масивів не обов' язково збігаються з оголошеним:
int [][,] b = new int[3] [,]; b[0] = new int[5,2];
На відміну від прямокутних масивів кожен індекс в ортогональних масивах виокремлено набором квадратних дужок:
a[0][0] = 100; b[0][0,0] = 100;
C# дає змогу присвоїти значення змінних одного типу змінним деяких інших типів. Це присвоєння може бути явним або неявним.
Виконати неявні перетворення для цілих типів можна лише тоді, коли перетворюються цілі у більш крупніші цілі або цілі без знака в цілі зі знаком такого ж розміру. В інших випадках компілятор генерує помилку. Наприклад,
byte b1 = 1; byte b2 = 2;
byte b = b1 + b2; //помилка компіляції
int i = b1 + b2; //коректне неявне перетворення

Довільне ціле можна перетворювати в типи float, double та decimal. Однак можлива втрата точності для перетворень із
int, uint, long або ulong до float та з long або ulong до double.
Дозволеними є також неявні перетворення з типу float у тип double та з типу char до ushort, int, uint, long, ulong, float,double і decimal.
Явне перетворення типів використовують з метою уникнення помилки компіляції при неявному перетворенні. Типовий синтаксис:
long l = 1000;
int і = (int)l;
Якщо значення, яке явно перетворюється, лежить за межами діапазону значень типу призначення, то помилка не виникає, а результат перетворення залежатиме від конкретного типу. Для перевірки коректності перетворення використовують оператор
checked:
int i = checked((int)l);
Якщо значення l виходить за межі значень типу int, то оператор checked згенерує виняткову ситуацію (переповнення).
Типи за значенням допускають перетворення лише у числові типи, типи enum і тип char.
Не можна безпосередньо перетворити тип bool до довільного іншого, і навпаки.
Тип стрічки перетворюється в інші типи (і навпаки) за допомогою відповідних методів .NET. Оскільки кожен клас C# є нащадком класу object, то він успадковує (або має власну реалізацію) метод ToString():
int i = 1; string s = i.ToString();
Для переводу стрічкового значення у числове або значення типу bool використовують метод Parse:
string s = "1"; int i = Int32.Parse(s);
Широкий набір методів перетворення типів надає також клас
System.Convert.
Упакування (boxing) та розпакування дає змогу перетворювати типи за значенням у типи за посиланням, і навпаки.
Приклад упакування: int i = 10; object obj = i;
Приклад розпакування: int j = (int)obj;
Розпаковувати можна лише змінну, яка попередньо була упакована. Змінна, у яку розпаковують об'єкт, повинна мати достатній розмір для розташування усіх байтів змінної, яку розпаковують.

Змінні та константи

Змінні оголошуються у C# із використанням такого синтаксису:
[модифікатори] тип_даних ідентифікатор;
Якщо в одному виразі оголошуються та ініціалізуються кілька змінних, то всі вони матимуть однаковий тип і модифікатори.
Змінні з однаковими іменами не можуть оголошуватися двічі в одній області видимості.
Ідентифікатори чутливі до регістру символів. Ідентифікатори повинні починатися літерою або символом "_". Ідентифікаторами не можуть бути ключові слова C# (76 слів).
Якщо необхідно використати ключове слово як ідентифікатор, то перед ним ставлять символ @. Цей символ дає вказівку компілятору сприймати такі символи як ідентифікатор, а не ключове слово.
Ідентифікатори можна записувати і з допомогою символів Unicode \uxxxx. Наприклад, \u050fidentifier.
Змінні з однаковими ідентифікаторами можна використовувати за умови їхнього розташування у різних областях видимості:
for (int i = 0; i < 10; i++) {...};
for (int i = 0; i < 50; i++) {...};
Дві змінні з однаковими ідентифікаторами можна використовувати у спільній області видимості лише у випадку, коли одна змінна - поле класу, а друга - локальна змінна, оголошена в методі класу. Наприклад:
public class A {
private int j = 10; public int Method() { int j = 20; return j + this.j;
}
}
Ключове слово this вказує, що елемент (змінна j) належить поточному екземпляру класу.
Модифікатори змінних описують ті чи інші особливості оголошуваних змінних. Перелічимо модифікатори змінних: internal, new, private, protected, public, readonly, static, const.
Модифікатори застосовують лише до полів (членів класів), однак не до локальних змінних. Змінна може мати декілька модифікаторів.
Модифікатор new використовують лише в класах, які є похідними від іншого, поля якого потрібно приховати.
Такі модифікатори утворюють групу модифікаторів доступу:
        public - змінна доступна скрізь як поле типу, якому вона належить;
        internal - змінна доступна лише поточному складеному модулю;
        protected - доступ до змінної відкритий лише з класу, якому вона належить, або з похідних класів;
        protected internal - те ж саме, що й protected, однак доступ лише з поточного складеного модуля;
        private - доступ до змінної лише з класу, у якому її оголошено.
За замовчуванням, поле є членом екземпляра класу. Тобто кожен екземпляр класу має власне поле (виділену ділянку пам'яті) із відповідним ідентифікатором. Якщо до оголошення поля додати модифікатор static, то це поле буде єдиним для всіх екземплярів класу.
Модифікатор readonly робить змінну доступною лише для читання. її значення можна встановити при першому оголошенні (для статичних змінних) або в конструкторі для типу, до якого вона належить (для нестатичних змінних).
Константи - це змінні, описані з використанням модифіка­тора const. Наприклад, 
const int a = 10;
Константи є подібними до статичних полів лише для читання із такими розбіжностями:
        локальні змінні та поля можуть бути оголошені константами;
        константи ініціалізуються в оголошенні;
        значення константи повинно бути обчислюваним під час компіляції, отож константу не можна ініціалізувати виразом із використанням змінної (однак можна використати readonly поле);
        константа завжди є статичною.
C# підтримує такі операції:
Категорія
Операції
Арифметичні
+ - * / %
Логічні
& | л ~ && || !

Конкатенація стрічок
+

Інкремент та декремент
++ —

Побітовий зсув
<< >>

Порівняння
== ! =
< > <= >=
Присвоєння
= +=
-= *= /= %= | =

Л= <<=
>>=
Доступ до членів (для об'єктів)


Індексування (для масивів та
[]

індексаторів)


Перетворення типу
()

Умовна (тернарна операція)
? :

Створення об' єкта
new

Інформація про тип
sizeof
is typeof
Керування винятками переповнення
checked
unchecked
Розіменування та адресація
* -> &
[]

Зазначимо, що чотири із цих операцій (sizeof, *, ->, &) доступні лише в „небезпечному коді" (unsafe - код, для якого C# не виконує перевірку безпечності за типом).
Операції інкремента та декремента (++ та —) можуть стояти як до, так і після змінної. Вирази x++ та ++x еквівалентні виразу x = x + 1. Однак префіксний оператор (++x) збільшує значення x до його використання у виразі. Навпаки, постфіксний оператор (x++) збільшує значення x після обчислення виразу. Наприклад:
bool b1, b2;
int x = 0;
b1 = ++x == 1; //b1=true
b2 = x++ == 2; //b2=false
Префіксний і постфіксний оператори декремента поводять себе аналогічно, однак зменшують операнд.
Інші скорочені оператори (+=, -=, *=, / = , %=, |=, Л=, <<= та >>=) вимагають двох операндів. їх використо­вують для зміни значення першого операнда шляхом виконання над ним арифметичної, логічної чи бітової операції. Наприклад, оператори x += y; та x = x + y; є еквівалентними.

Тернарний оператор ? : є скороченою формою конструкції if...else. Його назва вказує на використання трьох операндів. Оператор обчислює умову та повертає одне значення у випадку, якщо умова істинна, та інше - в протилежному випадку. Синтаксис оператора:
умова ? значення_істина : значення_хибність
Наприклад:
string s = (x >= 0 ? "Додатне" : "Від'ємне");
Оператори checked та unchecked
Використання оператора checked ми вже демонстрували, розглядаючи перетворення типів. Зауважимо, що перевірку на переповнення можна увімкнути відразу для всього коду, виконавши компіляцію програми з опцією /checked. Власне щодо цього випадку може виникнути потреба відміни перевірки на переповнення деякого коду, для чого й використовують оператор unchecked.
Оператор is тестує об'єкт на сумісність сумісним із певним типом. Наприклад, можна перевірити, чи сумісна змінна з типом
object:
int i = 1;
string s;
s = (i is object) ? "i має тип object" : String.Empty;
Зауважимо, що всі типи даних C# успадковують object, отож вираз i is object дорівнюватиме true.
Розмір (у байтах), необхідний для збереження у стеку змінної за значенням, можна визначити з допомогою оператора sizeof:
int L;
unsafe {
L = sizeof(double);
}
У результаті змінна L набуде значення 8.
Зазначимо, що оператор sizeof можна використовувати лише в блоках коду, який не є безпечним. За замовчуванням компілятор C# не сприймає такий код. Отож його підтримку необхідно активізувати або використанням опції командної стрічки компілятора / unsafe, або встановленням у значення true пункту Allow unsafe code blocks на сторінці властивостей проекту.
Оператор typeof повертає об'єкт Type, який представляє зазначений тип. Наприклад, typeof (string) поверне об'єкт Type, який представляє тип System.String. Це корисно за умови використання відображення для динамічного отримання інформації про об'єкт.
Наступна таблиця демонструє порядок дій операцій C#.
Група                                              Операції

() •
[] x++ xnew typeof

sizeof
checked unchecked
Унарні
+ - !
++x x та операції приведення

типів

Множення / ділення
* / %

Додавання / віднімання
+ -

Операції побітового зсуву
<< >>

Відношення
< > <=
>= is
Порівняння
== ! =

Побітовий AND
&

Побітовий XOR
І

Побітовий OR
л

Логічний AND
&&

Логічний OR
ІІ

Тернарний оператор
? :

Присвоєння
= += -
-= *= /= %= І= л= <<=

>>=


Оператори керування

C# має два умовні оператори: if та switch.
Синтаксис оператора if такий:
if ( умова) оператор (и)
[else
оператор (и) ]
Квадратні дужки позначають необов' язкову частину оператора if. Умова повинна повертати результат логічного типу: true або false. Якщо потрібно виконати декілька операторів, то їх об'єднують у блок (розташовують у фігурних дужках {...}).
Оператор switch...case призначений для вибору одного з варіантів подальшого виконання програми з декількох. Синтаксис оператора такий:
switch (вираз) { case константа: оператор (и) оператор переходу [default: оператор (и) оператор переходу]
}
Якщо вираз дорівнюватиме значенню однієї з позначок case, то виконуватиметься наступний за цією позначкою код. Зауважимо, що цей код не обов' язково оформляти як блок. Однак він повинен завершуватися оператором переходу (зазвичай, це оператор break). Єдиний виняток - кілька позначок case підряд:
switch (s) { case "A": case "D": i = 1; break; case "C":
i = 2; break; default i = 0; break;
}
Константа може бути константним виразом. Дві позначки case не можуть набувати однакового значення.
C# реалізує чотири типи циклів.
Цикл for має такий синтаксис:
for ([ініціалізатор]; [умова]; [ітератор]) оператор (и)
Тут ініціалізатор - вираз, який обчислюється до початку виконання циклу (зазвичай, тут ініціалізується локальна змінна, яку використовують як лічильник циклу), умова - вираз, який обчислюється перед виконанням кожної ітерації циклу (наприклад, перевірка того, що лічильник циклу менший за деяке значення), ітератор - вираз, який виконується після кожної ітерації циклу (наприклад, зміна лічильника циклу).
Кожен (або всі) із цих елементів може бути пропущений.
Цикл for є циклом із передумовою. Таким є й цикл while:
while (умова) оператор (и)
Цикл do...while є прикладом циклу з постумовою:
do оператор (и) while (умова);
Оскільки умова перевіряється після виконання тіла циклу, то хоча б одна ітерація виконається обов'язково.
Усі розглянуті цикли завершують свої ітерації, якщо умова набуде значення false.
C# пропонує ще один механізм циклів - foreach:
foreach (тип ідентифікатор in вираз) оператор (и)
Тут тип - тип ідентифікатора, ідентифікатор - змінна циклу, що представляє елемент колекції або масиву, а вираз - об'єкт колекції або масив (або вираз над ними).
Цикл foreach дає змогу проводити ітерацію по кожному об' єкту в контейнерному класі, який підтримує інтерфейс IEnumerable. До контейнерних класів належать масиви C#, класи колекцій у просторі імен System. Collection та означені користувачем класи колекцій:
int even = 0, odd = 0;
int[] arr = new int [] {0,1,2,5,7,8,11}; foreach (int i in arr) { if (i%2 == 0)
even++; else
odd++;
}
Зауважимо, що значення об' єкта в колекції всередині циклу foreach змінювати не можна.
Програма C# може містити позначки - ідентифікатор із двокрапкою. Оператор goto дає змогу передати керування стрічці програми з позначкою:
goto позначка;
Не можна передавати керування у блок коду, за межі класу, а також не можна вийти з блоку finally, розташованого після блоків try...catch.
Оператор goto може використовуватися для переходів усередині оператора switch. У цьому випадку синтаксис такий:
goto case константа;
goto default;
Оператор break використовують для виходу з коду позначки в операторі switch, а також для виходу із циклів for, foreach, while та do...while.
У циклах також можна використовувати оператор cont inue, який перериває поточну ітерацію та ініціює наступну.
Оператор return використовують для припинення роботи поточного методу та передачі керування в метод, який його активізував. Якщо метод повертає значення, то return повинен повернути значення відповідного типу:
return [ вираз];
Застосування оператора using (на відміну від директиви using) гарантує, що об'єкти, які інтенсивно використовують ресурси, будуть вивільнені відразу після закінчення роботи з ними. Синтаксис оператора:
using (об'єкт) оператор (и)
Тут об'єкт - це екземпляр класу, який реалізує інтерфейс IDisposable. Такі класи повинні містити реалізацію методу Dispose, який вивільняє ресурси, зайняті об'єктом класу. Метод Dispose викликається відразу після завершення блоку using.
Допускається наявність у списку оператора using декількох об'єктів:
using (Font MyFont = new Font("Arial", 10.0f), MyFont2 = new Font("Arial", 10.0f))
{
// використання MyFont та MyFont2
} // компілятор активізує Dispose для MyFont // та MyFont2
Під час виконання програми можливе виникнення помилок: ділення на нуль, вихід за межі діапазону тощо. Такі помилки називають винятком. Код може і явно активізувати виняток. Для коректного опрацювання таких ситуацій використовують блоки try, catch та finally.
У блок try розміщають код, який потенційно може спричинити виникнення винятків. Якщо під час виконання якогось із операторів цього блоку виникає помилка, то такі оператори не виконуються і керування передається на відповідний блок catch, розташований за блоком try. Якщо ж виняток не виникне, то оператори блоку catch не виконуватимуться.
Щоб гарантувати виконання деяких операторів незалежно від того, завершився код винятком чи ні, потрібно оформити блок finally.
Типові схеми блоків try, catch та finally такі:
try { оператор (и) }
catch { оператор(и) }
finally { оператор(и) }
або
try {  оператор (и) }
catch (тип винятку 1) { оператор (и) }
catch (тип винятку 2) { оператор (и) }
finally { оператор(и) }
Виняток - це об'єкт класу System.Exception або його спеціалізованих нащадків. Наприклад, catch(Exception e) пе­рехоплює всі винятки, а catch (DivideByZeroException e) - лише ділення на 0. Якщо існує набір конкретних типів винятків і блок catch (Exception e), його розташовують останнім.
Об'єкт e містить інформацію про виняток. Можна, наприклад, вивести стрічку e . ToString () з повідомленням про помилку або ім' я методу та класу, в якому виникла помилка, за допомогою e . StackTrace ().
Досить часто виникає потреба утворити власний об' єкт- виняток і згенерувати виняток. Наступний код демонструє цей процес:
Exception myEx = new Exception("myException"); myEx.HelpLink = "Ресурс недоступний."; myEx.Source = "MyDemoProject"; throw myEx; //генерування винятку

Немає коментарів:

Дописати коментар