Обработка исключений для C#
1. Что такое Exception?
В этом примере есть часть кода c ошибкой, которая получается из-за деления на 0. Деление на 0 вызывает исключение: DivideByZeroException
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class HelloException
{
public static void Main(string[] args)
{
Console.WriteLine("Three");
// Данное деление совершенно не имеет проблем.
int value = 10 / 2;
Console.WriteLine("Two");
// Данное деление тоже
value = 10 / 1;
Console.WriteLine("One");
int d = 0;
// Данное деление имеет проблему, делит на 0.
// Ошибка происходит здесь.
value = 10 / d;
// И строка кода ниже не будет выполнена.
Console.WriteLine("Let's go!");
Console.Read();
}
}
}
Вы можете увидеть уведомление ошибки на экране Console. Уведомление об ошибке очень четко, на какой строке кода она произошла.
Three
Two
One
- Программа выполняется как обычно с этапа (1), (2) до (5).
- На этапе (6) появляется проблема при делении на 0.
- Программа выскочила из функции main, и строка кода (7) не будет выполнена.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class HelloCatchException
{
public static void Main(string[] args)
{
Console.WriteLine("Three");
// Данное деление не имеет проблем.
int value = 10 / 2;
Console.WriteLine("Two");
// Данное деление не имеет проблем.
value = 10 / 1;
Console.WriteLine("One");
int d = 0;
try
{
// Данное деление имеет проблему, делит на 0.
// Ошибка происходит здесь.
value = 10 / d;
// Данный код не будет запущен.
Console.WriteLine("Value =" + value);
}
catch (DivideByZeroException e)
{
// Код в catch будет выполнен.
Console.WriteLine("Error: " + e.Message);
Console.WriteLine("Ignore...");
}
// Данный код выполняется.
Console.WriteLine("Let's go!");
Console.Read();
}
}
}
Three
Two
One
Error: Attempted to divide by zero.
Ignore...
Let't go!
- Шаги (1) - (6) являются полностью нормальными.
- Исключение происходит на этапе (7), проблема при делении на 0.
- Сразу же после звпрыгивает для выполнения команды в блоке catch, шаг (8) пропущен.
- Шаги (9), (10) выполнены.
- Шаги(11), (12) выполнены.
2. Иерархия исключений
- Самый высокий класс - Exception
- Два прямых подкласса - это SystemError и ApplicationException.
Kiểu ngoại lệ | Описание |
Exception | Основной класс всех исключений. |
SystemException | Основной класс всех исключений генерированных во время запуска программы. |
IndexOutOfRangeException | Выбрасывается во время запуска при доступе в элемент массива с неправильным индексом. |
NullReferenceException | Выбрасывается во время запуска при ссылке на объект null. |
AccessViolationException | Выбрасывается во время запуска при ссылке к недействительной памяти. |
InvalidOperationException | Выбрасывается методом при недействительном статусе. |
ArgumentException | Основной класс всех исключений связанных с аргументом (Argument). |
ArgumentNullException | Это подкласс ArgumentException, который выбрасывается методом, не позволяющим передачу аргументов null. |
ArgumentOutOfRangeException | Это подкласс ArgumentException, который выбрасывается методом когда аргумент не соответствует рамке позволяющей передачу. |
ExternalException | Основной класс для исключений или пришедших из внешней среды. |
COMException | Класс расширенный из ExternalException, исключение упаковывает информацию COM. |
SEHException | Класс расширенный из ExternalException, ловил все исключения из Win32. |
3. Поймать исключения используя try-catch
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class AgeException : ApplicationException
{
public AgeException(String message)
: base(message)
{
}
}
class TooYoungException : AgeException
{
public TooYoungException(String message)
: base(message)
{
}
}
class TooOldException : AgeException
{
public TooOldException(String message)
: base(message)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class AgeUtils
{
// Данный метод выполняет роль проверки возраста.
// Если возраст меньше 18 метод выбросит исключение TooYoungException
// Если возраст старше 40 метод выбросит исключение TooOldException
public static void checkAge(int age)
{
if (age < 18)
{
// Если возраст меньше 18, выбросится исключение
// Данный метод завершается здесь.
throw new TooYoungException("Age " + age + " too young");
}
else if (age > 40)
{
// Если возраст старше 40, выбросится исключение.
// Данный метод завершается здесь.
throw new TooOldException("Age " + age + " too old");
}
// Если возраст в рамке 18-40.
// Данный код запускается.
Console.WriteLine("Age " + age + " OK!");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class TryCatchDemo1
{
public static void Main(string[] args)
{
// Начать рекрутирование ...
Console.WriteLine("Start Recruiting ...");
// Проверить ваш возраст.
Console.WriteLine("Check your Age");
int age = 50;
try
{
AgeUtils.checkAge(age);
Console.WriteLine("You pass!");
}
catch (TooYoungException e)
{
// Оповещение об исключениях "слишком молодой" ..
Console.WriteLine("You are too young, not pass!");
Console.WriteLine(e.Message);
}
catch (TooOldException e)
{
// Оповещение об исключениях "превышает возраст" ..
Console.WriteLine("You are too old, not pass!");
Console.WriteLine(e.Message);
}
Console.Read();
}
}
}
Start Recruiting ...
Check your Age
You are too old, not pass!
Age 50 too old
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class TryCatchDemo2
{
public static void Main(string[] args)
{
// Начать рекрутирование ...
Console.WriteLine("Start Recruiting ...");
// Проверить ваш возраст.
Console.WriteLine("Check your Age");
int age = 15;
try
{
// Здесь может быбросить (throw) исключение TooOldException,
// или TooYoungException
AgeUtils.checkAge(age);
Console.WriteLine("You pass!");
}
// Если происходит исключение, вида AgeException
// Данный блок catch будет запущен.
catch (AgeException e)
{
Console.WriteLine("Your age invalid, you not pass");
Console.WriteLine(e.Message);
}
Console.Read();
}
}
}
Start Recruiting ...
Check your Age
Your age invalid, you not pass
Age 15 too young
4. Блок try-catch-finally
try {
// Сделать что-то здесь
} catch (Exception1 e) {
// Сделать что-то здесь
} catch (Exception2 e) {
// Сделать что-то здесь
} finally {
// Блок finally всегда выполняется
// Сделать что-то здесь
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class TryCatchFinallyDemo
{
public static void Main(string[] args)
{
String text = "001234A2";
int value = toInteger(text);
Console.WriteLine("Value= " + value);
Console.Read();
}
public static int toInteger(String text)
{
try
{
Console.WriteLine("Begin parse text: " + text);
// Здесь может произойти исключение FormatException
int value = int.Parse(text);
return value;
}
catch (FormatException e)
{
// В случае 'text' не является числом.
// Данный блок catch будет выполнен.
Console.WriteLine("Number format exception: " + e.Message);
return 0;
}
finally
{
Console.WriteLine("End parse text: " + text);
}
}
}
}
Begin parse text: 001234A2
Number format exception: Input string was not in a correct format.
End parse text: 001234A2
Value= 0
5. Обернуть Exception в другом Exception
- Person: Имитирует человека подающего заявление на работу в компанию с информацией:
- Имя, возраст, пол.
- GenderException: гендерное исключение.
- ValidateException: исключение оценки кандидата.
- ValidateUtils: Класс со статическим методом оценивает соответствие стандарту кандидатов.
- Стандартный возраст от 18 до 40 лет
- И мужчины.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class Person
{
public static readonly string MALE = "male";
public static readonly string FEMALE = "female";
private string name;
private string gender;
private int age;
public Person(string name, string gender, int age)
{
this.name = name;
this.gender = gender;
this.age = age;
}
public string GetName()
{
return name;
}
public string GetGender()
{
return gender;
}
public int GetAge()
{
return age;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class GenderException : ApplicationException
{
public GenderException(String message)
: base(message)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class ValidateException : ApplicationException
{
// Упаковать (wrap) Exception в Exception.
public ValidateException(Exception e) : base("Something invalid", e)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class ValidateUtils
{
// Метод проверяет человека, участвующего в рекрутировании.
public static void CheckPerson(Person person)
{
try
{
// Проверка возраста.
// Действительным является в рамках 18-40
// Данный метод может выбросить TooOldException,TooYoungException.
AgeUtils.checkAge(person.GetAge());
}
catch (Exception e)
{
// Если недействительно
// Обернуть данное исключение с помощью ValidateException, и выбросить (throw).
throw new ValidateException(e);
}
// Если это Женщина, то недействительно.
if (person.GetGender() == Person.FEMALE)
{
GenderException e = new GenderException("Do not accept women");
throw new ValidateException(e);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class WrapperExceptionDemo
{
public static void Main(string[] args)
{
// Кандидат участвует в рекрутировании.
Person person = new Person("Marry", Person.FEMALE, 20);
try
{
// Исключение может произойти здесь.
ValidateUtils.CheckPerson(person);
}
catch (ValidateException wrap)
{
// Получить настоящую причину.
// Может быть TooYoungException, TooOldException, GenderException.
Exception cause = wrap.GetBaseException();
if (cause != null)
{
Console.WriteLine("Message: " + wrap.Message);
Console.WriteLine("Base Exception Message: " + cause.Message);
}
else
{
Console.WriteLine("Message: " + wrap.Message);
}
}
Console.Read();
}
}
}
Age 20 OK!
Message: Something invalid
Base Exception Message: Do not accept women
6. Распространенные исключения
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class NullReferenceExceptionDemo
{
// Например это метод, который может вернуть строку null.
public static string GetString()
{
if (1 == 2)
{
return "1==2 !!";
}
return null;
}
public static void Main(string[] args)
{
// Это объект с ссылкой отличающейся от null.
string text1 = "Hello exception";
// Получить длину строки.
int length = text1.Length;
Console.WriteLine("Length text1 = " + length);
// Это объект с ссылкой (reference) null.
String text2 = GetString(); // text2 = null.
// Получить длину строки.
// NullReferenceException произойдет здесь.
length = text2.Length; // ==> Runtime Error!
Console.WriteLine("Finish!");
Console.Read();
}
}
}
Вы можете исправить приведенный выше код как приведено ниже, избегая NullReferenceException:
// Это объект с ссылкой null.
String text2 = GetString(); // ==> return null
// Проверить, чтобы удостовериться что 'text2' отличается от null,
// Вместо использования try-catch.
if (text2 != null)
{
length = text2.Length;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExceptionTutorial
{
class IndexOutOfRangeExceptionDemo
{
public static void Main(string[] args)
{
String[] strs = new String[] { "One", "Two", "Three" };
// Получить доступ в элемент индекса 0.
String str1 = strs[0];
Console.WriteLine("String at 0 = " + str1);
// Получить доступ в элемент индекса 5
// IndexOutOfRangeException происходит здесь.
String str2 = strs[5];
Console.WriteLine("String at 5 = " + str2);
Console.Read();
}
}
}
if (strs.length > 5)
{
String str2 = strs[5];
Console.WriteLine("String at 5 = " + str2);
}
else
{
Console.WriteLine("No elements with index 5");
}
Pуководства C#
- Наследование и полиморфизм в C#
- Что мне нужно для начала работы с C#?
- Быстрый обучение C# для начинающих
- Установите Visual Studio 2013 в Windows
- Абстрактный класс и Interface в C#
- Установите Visual Studio 2015 в Windows
- Сжатие и декомпрессия в C#
- Руководство по программированию многопоточности C#
- Руководство C# Delegate и Event
- Установите AnkhSVN в Windows
- Программирование C# для группы использующей Visual Studio и SVN
- Установить .Net Framework
- Access Modifier (Модификатор доступа) в C#
- Руководство C# String и StringBuilder
- Руководство C# Property
- Руководство C# Enum
- Руководство C# Structure
- Руководство C# Generics
- Обработка исключений для C#
- Руководство C# Date Time
- Манипулирование файлами и каталогами в C#
- Руководство CSharp Streams - двоичные потоки в C#
- Руководство Регулярное выражение C#
- Подключиться к базе данных SQL Server в C#
- Работа с базой данных SQL Server на C#
- Подключиться к базе данных MySQL в C#
- Работа с базой данных MySQL на C#
- Подключиться к базе данных Oracle в C# без Oracle Client
- Работа с базой данных Oracle на C#