2. Съдържание
• Изключения
– Видове грешки
– Връщане на код за състояние при извикване
– Проверка на състоянието
– Изключения
• Анотации и отражение
– Програмни единици
– Анотации
– Отражение
3. Обработка на грешки
• Видове грешки
– Compile time
• Грешки на компилатора по време на компилиране на приложението
• В следствие на грешки на програмиста
• Отстраняват се още по време на написване на приложението
– Run time
• Грешки на CLR по време на изпълнение на приложението
• В следствие на грешки на програмиста, непредвидени проблеми в средата,
входните данни, комуникацията и други изключителни ситуации
• Не се отстраняват, а се предвиждат
4. Обработка на грешки
// връщане на специален резултат
DbStatus status = ExecuteDbQuery("…");
switch (status)
{
case DbStatus.Ok:
break;
case DbStatus.NetworkError:
// разбутай кабела
break;
case DbStatus.FileAccessError:
// май имаме счупен диск?
break;
case DbStatus.FilePermissionError:
// кофти права за достъп до файла?
break;
}
• Old school подходи към
обработката на грешки
– Връщане на код за състояние
при извикване
– Прекалено много код при всяко
извикване
– Нужда от допълнителни
параметри
– Преправяне при нов код за
състояние
– Вероятност за излишни,
недостатъчни проверки и/или
повтарящ се код
5. Обработка на грешки
// проверка на състоянието
ExecuteDbQuery("…");
DbStatus status = GetDbStatus();
switch (status)
{
case DbStatus.Ok:
break;
case DbStatus.NetworkError:
// разбутай кабела
break;
case DbStatus.FileAccessError:
// май имаме счупен диск?
break;
case DbStatus.FilePermissionError:
// кофти права за достъп до файла?
break;
}
• Old school подходи към
обработката на грешки
– Проверка на състоянието
– Прекалено много код след всяко
извикване
– Нужда от допълнително
извикване
– Вероятност за излишни,
недостатъчни проверки и/или
повтарящ се код
– Нужда от познаване на тези
състояния от външен код
6. Обработка на грешки
• Какво беше “call stack”?
– Спомени от темата за рекурсия
– Първо, какво беше “stack”?
• Колекция от елементи
• Операция: добавяне на елемент в края (push)
• Операция: взимане на елемент от края (pop)
• LIFO (Last-In-First-Out структура)
– Та, какво е “call stack”?
• Структура, която .NET Framework поддържа по време на изпълнение
• Записва се информация за последното извикване на метод:
– Локалните променливи по време на извикването
– Мястото на извикването
– Параметрите, с които е направено
• С други думи: дава информация от къде идваме, за да се върнем обратно
7. Обработка на грешки
• Какво е „изключение“?
– Изключение/изключителна ситуация
– Проверка за възникване на изключение
– Прихващане на изключения
– Финализиране след проверка за изключение
– Предизвикване на изключение
• Какво се случва при изключение?
– Прекратява се изпълнението на текущия код
– Намира се блок обработващ съответния тип изключения
– Ако не съществува такъв блок, изпълнението приключва с грешка
– Финализиране, независимо дали е възникнала грешка или не
8. Обработка на грешки
• Изключения в C#
– Информацията за изключения се пренася от обекти
– Обектите са от вградения клас Exception или негов наследник
• Свойства Message, StackTrace и InnerException
– .NET Framework предлага множество вградени изключения
• ArgumentException, IndexOutOfRangeException, IOException и др.
– Програмистът може да направи свой вид изключение
• Конвенцията е наименованието на класа да завършва с Exception
9. Обработка на грешки
try
{
// Операции при нормална работа
// …
// Предизвикване на изключение
throw new DbException("DB error.");
}
catch (ArgumentException ex)
{
// Обработване на ArgumentException
}
catch (Exception ex)
{
// Обработване на Exception
}
finally
{
// Винаги изпълнявани операции
}
• Изключения в C#
– Конструкция try … catch … finally
• Блоковете catch и finally не за
задължителни, но поне единият
трябва да присъства
• Възможно е наличието на повече от
един catch блок
• В скобите на catch блок се указва
типа на прихващаните изключения
– Предизвикване на изключение с
throw
• Възможно е предизвикване на
изключение в catch блока
• Предизвикване на оригиналното
изключение
10. Обработка на грешки
// почистване
FileStream stream =
File.OpenRead(@"C:File.txt");
try
{
// работа с потока stream
}
finally
{
stream.Dispose();
}
// съкратен запис на горното
using (FileStream stream =
File.OpenRead(@"C:File.txt"))
{
// работа с потока stream
}
• Конструкцията using
– Интерфейсът IDisposable
• Декларира метод Dispose
– Съкратен запис и яснота на кода
11. Обработка на грешки
try
{
// прекратява нишката
Thread.Abort();
}
catch (ThreadAbortException)
{
// … някакъв код…
// все едно тук пише:
throw;
// освен ако:
// Thread.ResetAbort();
}
• Какво е „нишка“?
– Отделна последователност от
инструкции независимо
управлявани от ОС
– Многонишковост
• ThreadAbortException
– Специално изключение
използвано при прекратяване на
нишка
– Предизвиква се автоматично
отново в края на catch блока
– … освен ако не се извика
Thread.ResetAbort()
13. Анотации и отражение
• Програмни единици
– Application domain – механизъм за
изолиране на изпълнението на
различни приложения
– Assembly – компилирана библиотека
от код (process & library assemblies)
– Module – съдържа код, метаданни
и ресурси
– …
14. Анотации и отражение
• Какво е „анотация“?
– Метод за асоцииране на метаданни или декларативна
информация с различни програмни единици
– Анотациите се добавят от програмиста по време на разработка на
съответните програмни единици
– Метаданните могат да съдържат информация за:
• Инструкции за работа на компилатора
• Инструкции за работа при компилиране и изпълнение
• Друга машинно обработваема информация
15. Анотации и отражение
• Анотации в .NET Framework
– Анотациите са реализирани като обекти (т.нар. атрибути)
– Обектите са от клас наследяващ класа Attribute
• Атрибутите могат да имат полета, свойства, методи и т.н.
• Атрибутите могат да приемат аргументи
• Към една програмна единица могат да се прилагат повече от един атрибути
– .NET Framework предлага множество вградени атрибути
• AssemblyNameAttribute, AssemblyVersionAttribute и др.
• AssemblyCompanyAttribute, AssemblyCopyrightAttribute и др.
• ObsoleteAttribute
• SerializableAttribute и NonSerializedAttribute
• AttributeUsageAttribute
17. Анотации и отражение
• Какво е „отражение“?
– Техника за получаване на информация за програмни единици по
време на изпълнение, обръщение към тях и достъпването им
– Отражението в частност може да се използва за обработка на
анотациите
– Отражението може да се използва за сериализиране и
десериализиране на данни
18. Анотации и отражение
• Отражение в .NET Framework
– Реализира се чрез използване на функционалността в
пространството на имена System.Reflection и класа System.Type
– System.Reflection.Emit дава възможност и за създаване на изпълним
CIL (Common Intermediate Language) код от приложение (напр.
написването на собствен компилатор)
– Може да се извлича разнообразна информация за различни
компоненти (assemblies, модули, типове данни, методи,
конструктори, полета, свойства, параметри, събития и др.)
20. Задачи за упражнение
• Модифицирайте задачата „Геометрични фигури“ от
предходните упражнения, така че:
– в началото на конструкторите и методите с параметри, да се
проверяват за коректност техните стойности и да се предизвикват
съответните изключения
– при въвеждане на данни за даден обект, да се проверява тяхната
коректност и да се предизвикват различни по вид изключения
според ситуацията
– при изчисляване на параметрите за даден обект, да се проверява
наличието на всички необходими данни и, ако липсват такива, да
се предизвиква изключение
– в основната програма, да се прихванат различните изключения, да
се изведе разбираемо съобщение и да се реагира адекватно на
различните видове изключения
21. Задачи за упражнение
• Създайте C# библиотека, която да съдържа атрибута
DeveloperInfoAttribute, който:
– Съдържа информация за име, e-мейл адрес и телефон за контакт
на разработчика
– Името и е-мейл адресът са задължителни, докато телефонният
номер не е
– Атрибутът да може да се прилага повече от веднъж върху всякакви
програмни единици
– Поставете така направения атрибут на всички възможни програмни
единици, като попълните информация за поне няколко
разработчика
22. Задачи за упражнение
• Създайте аналитично приложение, което да:
– изчита от клавиатурата наименованието на *.dll или *.exe файл
– опитва да зареди файла като assembly
– има добавена референция към проекта от предходното
упражнение
– намира програмните единици, които имат атрибут
DeveloperInfoAttribute и извежда информацията от атрибута
– има добавена референция към проекта „Геометрични фигури“
– намира всички класове наследяващи класа Object2D, извежда
тяхното наименование и техните DeveloperInfoAttribute атрибути,
ако имат такива (иначе надпис „No developer info for this class.”)