Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Основы обработки исключений






Далеко не всегда ошибки случаются по вине того, кто кодирует приложение. Иногда приложение генерирует ошибку из-за действий конечного пользователя, или же ошибка вызвана контекстом среды, в которой выполняется код. В любом случае вы всегда должны ожидать возникновения ошибок в своих приложениях и проводить кодирование в соответствии с этими ожиданиями.

В.NET Framework предусмотрена развитая система обработки ошибок. Механизм обработки ошибок C# позволяет закодировать пользовательскую обработку для каждого типа ошибочных условий, а также отделить код, потенциально порождающий ошибки, от кода, обрабатывающего их.

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

Программные ошибки (bugs)

Так обычно называются ошибки, которые допускает программист. Например, предположим, что приложение создается с помощью неуправляемого языка С++. Если динамически выделяемая память не освобождается, что чревато утечкой памяти, появляется программная ошибка.

Пользовательские ошибки (user errors)

В отличие от программных ошибок, пользовательские ошибки обычно возникают из-за тех, кто запускает приложение, а не тех, кто его создает. Например, ввод конечным пользователем в текстовом поле неправильно оформленной строки может привести к генерации ошибки подобного рода, если в коде не была предусмотрена возможность обработки некорректного ввода.

Исключения (exceptions)

Исключениями, или исключительными ситуациями, обычно называются аномалии, которые могут возникать во время выполнения и которые трудно, а порой и вообще невозможно, предусмотреть во время программирования приложения. К числу таких возможных исключений относятся попытки подключения к базе данных, которой больше не существует, попытки открытия поврежденного файла или попытки установки связи с машиной, которая в текущий момент находится в автономном режиме. В каждом из этих случаев программист (и конечный пользователь) мало что может сделать с подобными " исключительными" обстоятельствами.

По приведенным выше описаниям должно стать понятно, что структурированная обработка исключений в.NET представляет собой методику, предназначенную для работы с исключениями, которые могут возникать на этапе выполнения. Даже в случае программных и пользовательских ошибок, которые ускользнули от глаз программиста, однако, CLR будет часто автоматически генерировать соответствующее исключение с описанием текущей проблемы. В библиотеках базовых классов.NET определено множество различных исключений, таких как FormatException, IndexOutOfRangeException, FileNotFoundException, ArgumentOutOfRangeException и т.д.

В терминологии.NET под " исключением" подразумеваются программные ошибки, пользовательские ошибки и ошибки времени выполнения. Прежде чем погружаться в детали, давайте посмотрим, какую роль играет структурированная обработка исключений, и чем она отличается от традиционных методик обработки ошибок.

Роль обработки исключений в.NET

До появления.NET обработка ошибок в среде операционной системы Windows представляла собой весьма запутанную смесь технологий. Многие программисты включали собственную логику обработки ошибок в контекст интересующего приложения. Например, команда разработчиков могла определять набор числовых констант для представления известных сбойных ситуаций и затем применять эти константы в качестве возвращаемых значений методов.

Помимо приемов, изобретаемых самими разработчиками, в API-интерфейсе Windows определены сотни кодов ошибок с помощью #define и HRESULT, а также множество вариаций простых булевских значений (bool, BOOL, VARIANT BOOL и т.д.). Более того, многие разработчики СОМ-приложений на языке С++ (а также VB 6) явно или неявно применяют небольшой набор стандартных СОМ-интерфейсов (наподобие ISupportErrorlnfo. IErrorlnfo или ICreateErrorlnfо) для возврата СОМ-клиенту понятной информации об ошибках.

Очевидная проблема со всеми этими более старыми методиками — отсутствие симметрии. Каждая из них более-менее вписывается в рамки какой-то одной технологии, одного языка и, пожалуй, даже одного проекта. В.NET поддерживается стандартная методика для генерации и выявления ошибок в исполняющей среде, называемая структурированной обработкой исключений (SEH - structured exception handling).

Прелесть этой методики состоит в том, что она позволяет разработчикам использовать в области обработки ошибок унифицированный подход, который является общим для всех языков, ориентированных на платформу.NET. Благодаря этому, программист на C# может обрабатывать ошибки почти таким же с синтаксической точки зрения образом, как и программист на VB и программист на С++, использующий C++/CLI.

Дополнительное преимущество состоит в том, что синтаксис, который требуется применять для генерации и перехвата исключений за пределами сборок и машин, тоже выглядит идентично. Например, при написании на C# службы Windows Communication Foundation (WCF) генерировать исключение SOAP для удаленного вызывающего кода можно с использованием тех же ключевых слов, которые применяются для генерации исключения внутри методов в одном и том же приложении.

Еще одно преимущество механизма исключений.NET состоит в том, что в отличие от запутанных числовых значений, просто обозначающих текущую проблему, они представляют собой объекты, в которых содержится читабельное описание проблемы, а также детальный снимок стека вызовов на момент, когда изначально возникло исключение. Более того, конечному пользователю можно предоставлять справочную ссылку, которая указывает на определенный URL-адрес с описанием деталей ошибки, а также специальные данные, определенные программистом.

Составляющие процесса обработки исключений в.NET

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

тип класса, который представляет детали исключения;

член, способный генерировать (throw) в вызывающем коде экземпляр класса исключения при соответствующих обстоятельствах;

блок кода на вызывающей стороне, ответственный за обращение к члену, в котором может произойти исключение;

блок кода на вызывающей стороне, который будет обрабатывать (или перехватывать (catch)) исключение в случае его возникновения.

Принимая во внимание, что.NET Framework включает большое количество предопределенных классов исключений, возникает вопрос: как их использовать в коде для перехвата ошибочных условий? Для того чтобы справиться с возможными ошибочными ситуациями в коде C#, программа обычно делится на блоки трех разных типов:

Блоки try инкапсулируют код, формирующий часть нормальных действий программы, которые потенциально могут столкнуться с серьезными ошибочными ситуациями.

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

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

Try и catch

Основу обработки исключительных ситуаций в C# составляет пара ключевых слов try и catch. Эти ключевые слова действуют совместно и не могут быть использованы порознь. Ниже приведена общая форма определения блоков try/catch для обработки исключительных ситуаций:

try {

}

 

catch (ExcepType1 exOb) {

}

catch (ExcepType2 exOb) {

}

...

где ExcepType — это тип возникающей исключительной ситуации. Когда исключение генерируется оператором try, оно перехватывается составляющим ему пару оператором catch, который затем обрабатывает это исключение. В зависимости от типа исключения выполняется и соответствующий оператор catch. Так, если типы генерируемого исключения и того, что указывается в операторе catch, совпадают, то выполняется именно этот оператор, а все остальные пропускаются. Когда исключение перехватывается, переменная исключения exOb получает свое значение. На самом деле указывать переменную exOb необязательно. Так, ее необязательно указывать, если обработчику исключений не требуется доступ к объекту исключения, что бывает довольно часто. Для обработки исключения достаточно и его типа.

Следует, однако, иметь в виду, что если исключение не генерируется, то блок оператора try завершается как обычно, и все его операторы catch пропускаются. Выполнение программы возобновляется с первого оператора, следующего после завершающего оператора catch. Таким образом, оператор catch выполняется лишь в том случае, если генерируется исключение.

Давайте рассмотрим пример, в котором будем обрабатывать исключение, возникающее при делении числа на 0:

Последствия неперехвата исключений

Перехват одного из стандартных исключений, как в приведенном выше примере, дает еще одно преимущество: он исключает аварийное завершение программы. Как только исключение будет сгенерировано, оно должно быть перехвачено каким-то фрагментом кода в определенном месте программы. Вообще говоря, если исключение не перехватывается в программе, то оно будет перехвачено исполняющей системой. Но дело в том, что исполняющая система выдаст сообщение об ошибке и прервет выполнение программы.

Класс Exception

Все определяемые на уровне пользователя и системы исключения в конечном итоге всегда наследуются от базового класса System.Exception, который, в свою очередь, наследуется от класса System.Object. Ниже показано, как в целом выглядит этот класс (обратите внимание, что некоторые его члены являются виртуальными и, следовательно, могут переопределяться в производных классах):

public class Exception: ISerializable, _Exception

{

public Exception(string message, Exception innerException);

public Exception(string message);

public Exception();

...

public virtual Exception GetBaseException();

public virtual void GetObjectData(Serializationlnfо info, StreamingContext context);

public virtual IDictionary Data { get; }

public virtual string HelpLink { get; set; }

public Exception InnerException { get; }

public virtual string Message { get; }

public virtual string Source { get; set; }

public virtual string StackTrace { get; }

public MethodBase TargetSite { get; }

...

}

Нетрудно заметить, что многие из содержащихся в System.Exception свойств являются по своей природе доступными только для чтения. Это объясняется тем, что для каждого из них значения, используемые по умолчанию, обычно поставляются в производных классах. Например, в производном классе IndexOutOfRangeException поставляется сообщение по умолчанию " Index was outside the bounds of the array" (" Индекс вышел за границы массива").

В следующей таблице приведено краткое описание некоторых наиболее важных свойств класса System.Exception:

Свойства класса Exception
Свойство Описание
Data Это свойство, доступное только для чтения, позволяет извлекать коллекцию пар " ключ/значение" (представленную объектом, реализующим интерфейс IDictionary), которая предоставляет дополнительную, определяемую программистом, информацию об исключении. По умолчанию эта коллекция является пустой.
HelpLink Это свойство позволяет получать или устанавливать URL-адрес, по которому доступен справочный файл или веб-сайт с детальным описанием ошибки.
InnerException Это свойство, доступное только для чтения, может применяться для получения информации о предыдущем исключении или исключениях, которые послужили причиной возникновения текущего исключения. Запись предыдущих исключений осуществляется путем их передачи конструктору самого последнего исключения.
Message Это свойство, доступное только для чтения, возвращает текстовое описание соответствующей ошибки. Само сообщение об ошибке задается в передаваемом конструктору параметре.
Source Это свойство позволяет получать или устанавливать имя сборки или объекта, который привел к выдаче исключения.
StackTrace Это свойство, доступное только для чтения, содержит строку с описанием последовательности вызовов, которая привела к возникновению исключения. Как нетрудно догадаться, это свойство очень полезно во время отладки или для сохранения информации об ошибке во внешнем журнале ошибок.
TargetSite Это свойство, доступное только для чтения, возвращает объект MethodBase с описанием многочисленных деталей метода, который привел к выдаче исключения (вызов вместе с ним ToString() позволяет идентифицировать этот метод по имени)

20. Понятие «Классы». Спецификаторы

Классы – содержат данные, зависящие от свойств объектов класса, функции, определяющие их поведение, а также события, на которые можно реагировать объект класса. Все классы библиотеки.NET имеют одного общего предка – object и ориентированы в единую иерархическую структуру.

Внутри нее классы логически сгруппированы в так называемые пространства имен, которые служат для упорядочения имен классов и предотвращение конкретных имен.

Любая платформа.NET использует пространство System. В нем отражены классы, которые обеспечивают базовую функциональность

using System

using System.WindowsForm

namespace WindowsFormApplication1

{ public partial class Form1: Form

{ public Form

using System

namespace ConsoleApplication;

{

class Class1

{static void Main ()

{Console.WriteLine (“Введите число”);

string s=Console.ReadLine ();

Console.WriteLine (“Вы ввели ”+s);

}

}

}

}

}






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.