Нема описа

ababin 55a48cde48 Добавить 'README.md' пре 7 месеци
.idea 47a9373c10 laba пре 7 месеци
ConsoleApp16 47a9373c10 laba пре 7 месеци
ConsoleApp16.sln 47a9373c10 laba пре 7 месеци
README.md 55a48cde48 Добавить 'README.md' пре 7 месеци

README.md

int x = 5;
int y = x / 0;
Console.WriteLine($"Результат: {y}");
Console.WriteLine("Конец программы");
Console.Read();

В данном случае происходит деление числа на 0, что приведет к генерации исключения. И при запуске приложения в консоли увидим сообщение об ошибке: Вывод:

Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.
   at Program.<Main>$(String[] args) in /home/kei/RiderProjects/tryCatch/Program.cs:line 2

Process finished with exit code 134.

Чтобы избежать подобного аварийного завершения программы, следует использовать для обработки исключений конструкцию try...catch...finally. Так, перепишем пример следующим образом:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
catch
{
    Console.WriteLine("Возникло исключение!");
}
finally
{
    Console.WriteLine("Блок finally");
}
Console.WriteLine("Конец программы");
Console.Read();

Вывод:

Возникло исключение!
Блок finally
Конец программы

Следует отметить, что в этой конструкции обязателен блок try. При наличии блока catch мы можем опустить блок finally:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
catch
{
    Console.WriteLine("Возникло исключение!");
}

Вывод:

Возникло исключение!

Process finished with exit code 0.

Блок catch можно опустить,при наличии блока finally:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
finally
{
    Console.WriteLine("Блок finally");
}

Вывод:

Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.                                 
   at Program.<Main>$(String[] args) in C:\Users\hardb\RiderProjects\ConsoleApp16\ConsoleApp16\Program.cs:line 4
Блок finally

Process finished with exit code -1,073,741,676.

Обработка исключений и условные конструкции Ряд исключительных ситуаций может быть предвиден разработчиком. Например, пусть программа предусматривает ввод числа и вывод его квадрата:

Console.WriteLine("Введите число");
int x;
string input = Console.ReadLine();
if (Int32.TryParse(input, out x))
{
    x *= x;
    Console.WriteLine("Квадрат числа: " + x);
}
else
{
    Console.WriteLine("Некорректный ввод");
}
Console.Read();

Вывод:

Введите число
3
Квадрат числа: 9

Блок catch и фильтры исключений Обрабатывает любое исключение, которое возникло в блоке try. Выше уже был продемонстрирован пример подобного блока. Например, обработаем только исключения типа DivideByZeroException:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
catch(DivideByZeroException)
{
    Console.WriteLine("Возникло исключение DivideByZeroException");
}

Вывод: Возникло исключение DivideByZeroException Фильтры исключений В этом случае обработка исключения в блоке catch производится только в том случае, если условие в выражении when истинно.

int x = 1;
int y = 0;
 
try
{
    int result = x / y;
}
catch(DivideByZeroException) when (y==0 && x == 0)
{
    Console.WriteLine("y не должен быть равен 0");
}
catch(DivideByZeroException ex)
{
    Console.WriteLine(ex.Message);
}

Класс Exception обработаем исключения типа Exception:

try
{
    int x = 5;
    int y = x / 0;
    Console.WriteLine($"Результат: {y}");
}
catch (Exception ex)
{
    Console.WriteLine($"Исключение: {ex.Message}");
    Console.WriteLine($"Метод: {ex.TargetSite}");
    Console.WriteLine($"Трассировка стека: {ex.StackTrace}");
}

Console.Read();

Вывод:

Исключение: Attempted to divide by zero.
Метод: Void <Main>$(System.String[])
Трассировка стека:    at Program.<Main>$(String[] args) in C:\Users\hardb\RiderProjects\ConsoleApp16\ConsoleApp16\Program.cs:line 4

И при необходимости мы можем разграничить обработку различных типов исключений, включив дополнительные блоки catch:

try
{
    int[] numbers = new int[4];
    numbers[7] = 9;     // IndexOutOfRangeException

    int x = 5;
    int y = x / 0;  // DivideByZeroException
    Console.WriteLine($"Результат: {y}");
}
catch (DivideByZeroException)
{
    Console.WriteLine("Возникло исключение DivideByZeroException");
}
catch (IndexOutOfRangeException ex)
{
    Console.WriteLine(ex.Message);
}
            
Console.Read();

Вывод: Index was outside the bounds of the array. Рассмотрим другую ситуацию:

try
{
    object obj = "you";
    int num = (int)obj;     // InvalidCastException
    Console.WriteLine($"Результат: {num}");
}
catch (DivideByZeroException)
{
    Console.WriteLine("Возникло исключение DivideByZeroException");
}
catch (IndexOutOfRangeException)
{
    Console.WriteLine("Возникло исключение IndexOutOfRangeException");
}
            
Console.Read();

Вывод:

Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Int32'.
   at Program.<Main>$(String[] args) in C:\Users\hardb\RiderProjects\ConsoleApp16\ConsoleApp16\Program.cs:line 4

Создание классов исключений Если нас не устраивают встроенные типы исключений, то мы можем создать свои типы. Базовым классом для всех исключений является класс Exception, соответственно для создания своих типов мы можем унаследовать данный класс.

Допустим, у нас в программе будет ограничение по возрасту:

try
{
    Person p = new Person { Name = "Tom", Age = 17 };
}
catch (Exception ex)
{
    Console.WriteLine($"Ошибка: {ex.Message}");
}
Console.Read();

class Person
{
    private int age;
    public string Name { get; set; }
    public int Age
    {
        get { return age; }
        set
        {
            if (value < 18)
            {
                throw new Exception("Лицам до 18 регистрация запрещена");
            }
            else
            {
                age = value;
            }
        }
    }
}

Вывод: Ошибка: Лицам до 18 регистрация запрещена

Иногда удобнее использовать свои классы исключений. Например можно обработать только искучения класса (Persone).Для этих целей мы можем сделать специальный класс PersonException:

class PersonException : Exception
{
    public PersonException(string message)
        : base(message)
    { }
}
try
{
    Person p = new Person { Name = "Tom", Age = 17 };
}
catch (PersonException ex)
{
    Console.WriteLine("Ошибка: " + ex.Message);
}
Console.Read();

class Person
{
    private int age;
    public int Age
    {
        get { return age; }
        set
        {
            if (value < 18)
                throw new PersonException("Лицам до 18 регистрация запрещена");
            else
                age = value;
        }
    }
}

Поиск блока catch при обработке исключений Если код, который вызывает исключение, не размещен в блоке try или помещен в конструкцию try..catch, которая не содержит соответствующего блока catch для обработки возникшего исключения, то система производит поиск соответствующего обработчика исключения в стеке вызовов.

Например, рассмотрим следующую программу:

try
{
    TestClass.Method1();
}
catch (DivideByZeroException ex)
{
    Console.WriteLine($"Catch в Main : {ex.Message}");
}
finally
{
    Console.WriteLine("Блок finally в Main");
}
Console.WriteLine("Конец метода Main");
Console.Read();

class TestClass
{
    public static void Method1()
    {
        try
        {
            Method2();
        }
        catch (IndexOutOfRangeException ex)
        {
            Console.WriteLine($"Catch в Method1 : {ex.Message}");
        }
        finally
        {
            Console.WriteLine("Блок finally в Method1");
        }
        Console.WriteLine("Конец метода Method1");
    }
    static void Method2()
    {
        try
        {
            int x = 8;
            int y = x / 0;
        }
        finally
        {
            Console.WriteLine("Блок finally в Method2");
        }
        Console.WriteLine("Конец метода Method2");
    }
}

Вывод:

Блок finally в Method2
Блок finally в Method1
Catch в Main : Attempted to divide by zero.
Блок finally в Main
Конец метода Main

Генерация исключения и оператор throw В нашей программе происходит ввод строки и нужно,чтобы ,если длина строки будет больше 6 символов, возникало исключение:

try
{
    Console.Write("Введите строку: ");
    string message = Console.ReadLine();
    if (message.Length > 6)
    {
        throw new Exception(
            "Длина строки больше 6 символов");
    }
}
catch (Exception e)
{
    Console.WriteLine($"Ошибка: {e.Message}");
}
Console.Read();

Вывод:

Введите строку: 1234567
Ошибка: Длина строки больше 6 символов

Назначение и объявление

double? pi = 3.14;
char? letter = 'a';

int m2 = 10;
int? m = m2;

bool? flag = null;

// An array of a nullable value type:
int?[] arr = new int?[10];

Проверка экземпляра типа значения, допускающего значение NULL

int? a = 42;
if (a is int valueOfA)
{
    Console.WriteLine($"a is {valueOfA}");
}
else
{
    Console.WriteLine("a does not have a value");
}

Вывод: a is 42 В следующем примере используется свойство HasValue, чтобы проверить, содержит ли переменная значение, перед его отображением:

int? b = 10;
if (b.HasValue)
{
    Console.WriteLine($"b is {b.Value}");
}
else
{
    Console.WriteLine("b does not have a value");
}

Можно также сравнить переменную типа значения, допускающего значение NULL, с null вместо использования свойства HasValue, как показано в следующем примере:

int? c = 7;
if (c != null)
{
    Console.WriteLine($"c is {c.Value}");
}
else
{
    Console.WriteLine("c does not have a value");
}

Преобразование из типа значения, допускающего значение NULL, в базовый тип

int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}");  // output: b is 28

int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}");  // output: d is -1

Операторы с нулификацией

int? a = 10;
int? b = null;
int? c = 10;

a++;        // a is 11
a = a * c;  // a is 110
a = a + b;  // a is null

В следующем примере показано, что 10 не больше и не равно значению null, не меньше чем null.

int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False

int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True

Оператор ?? Оператор ?? называется оператором null-объединения. Он применяется для установки значений по умолчанию для типов, которые допускают значение null. Оператор ?? возвращает левый операнд, если этот операнд не равен null. Иначе возвращается правый операнд. При этом левый операнд должен принимать null. Посмотрим на примере:

object x = null;
object y = x ?? 100;  // равно 100, так как x равен null
 
object z = 200;
object t = z ?? 44; // равно 200, так как z не равен null