Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OSISP Part 3.DOC
Скачиваний:
42
Добавлен:
11.05.2015
Размер:
360.45 Кб
Скачать
  1. События в среде .Net; реализация событий посредством делегатов.

using System;

// Введем собственный делегат, не принимающий

// никаких значений.

delegate void MyDelegate();

// Это тестовый класс, он представляет собой гипотетический

// компонент кнопки.

class Button

{

// Введем общедоступное событие, к которому

// смогут подключаться все желающие.

public event MyDelegate Click;

// Данная функция необходима для того, чтобы

// симулировать событие нажатия на кнопку.

public void SimulateClick()

{

// Вызываем функции, связанные с событием Click,

// предварительно проверив, зарегистрировался

// ли кто-нибудь в данном событии.

if (Click != null)

Click();

}

};

class App

{

static void Main()

{

// Создаем экземпляр класса/компонента.

Button sc = new Button();

// Добавляем обработчик к его событию.

sc.Click += new MyDelegate(Handler);

// Сами вызовем функцию, которая инициирует

// возникновение события нажатия на кнопку.

sc.SimulateClick();

}

// А это функция-обработчик события нажатия на кнопку.

static void Handler()

{

Console.WriteLine("Hello, World!");

}

};

Рассмотрим, какой код поддержки события был создан компилятором. Для этого изучим IL- код.

Во-первых, компилятор создал поле-делегат, в котором хранятся все зарегистрированные обработчики события..field private class MyDelegate Click

Обратите внимание, что поле является закрытым и может быть использовано только из самого класса, исключая даже его потомков (private). Также компилятор создал одноименное специализированное свойство, в котором указаны методы, реализующие внешнюю работу с данным событием. Причем необходимо отметить, что это свойство по умолчанию является общедоступным..event MyDelegate Click

{

.addon instance void Button::add_Click(class MyDelegate)

.removeon instance void Button::remove_Click(class MyDelegate)

}

События — это члены типа, обес­печивающие такого рода взаимодействие. Тип, в котором определены события, как минимум поддерживает:

■ регистрацию статического метода типа или экземплярного метода объекта, заинтересованных в получении уведомления о событии;

■ отмену регистрации статического метода типа или экземплярного метода объек­та, получающих уведомления о событии;

■ уведомление зарегистрированных методов о том, что событие произошло.

Типы могут предоставлять эту функциональность при определении событий, так как они поддерживают список зарегистрированных методов. Когда событие происходит, тип уведомляет об этом все зарегистрированные методы.

  1. Исключительные ситуации и реакция на них в среде .Net.

private void SomeMethod() {

try {

// Внутрь блока try помещают код, требующий корректного

// восстановления работоспособности или очистки ресурсов.

}

catch (InvalidOperationException) {

// В такие блоки catch помещают код, который должен восстанавливаться

// после исключений типа InvalidOperationException (или любого исключения,

// производного от него).

}

catch (IOException) {

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

catch {

// В такие блоки catch помещают код, который должен

// восстанавливаться после исключений любого типа.

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

// генерируют повторно.

throw;

}

finally {

// Внутрь блоков finally помещают код, выполняющий очистку ресурсов после любых действий, начатых в блоке try. Код из этого блока исполняется ВСЕГДА независимо от того, было исключение или нет.

}

// Код после блока finally исполняется, если в блоке try не было исключения или если исключение было перехвачено блоком catch и не было сгенерировано то же самое или другое исключение.)

«Допустим, у меня есть приложение, которое должно считать из файла структуру размером в 20 байт, но файл оказался лишь 10-байтовым. В этом случае я не ожидаю встретить конец файла при чтении, но это неожидан­но происходит. Наверное, здесь должно возникнуть исключение, не так ли?» Фак­тически большинство файлов содержит структурированные данные. Довольно ред­ко бывает так, что приложение читает из файла байт за байтом, тут же обрабаты­вая прочитанные байты, пока не достигнет конца файла. Поэтому я думаю, логичнее будет, если при попытке чтения за пределами файла метод Read всегда будет ге­нерировать исключение.

При разработ­ке типа вы сначала пытаетесь представить себе разнообразные ситуации, в кото­рых будет применяться тип. Сначала определяется имя типа — обычно существи­тельное, например FileStream (файловый поток) или StringBuilder (построитель строк), затем приступают к определению членов (типов данных свойств, парамет­ров методов, возвращаемых значений и т. п.). Особенности определения этих членов становятся программным интерфейсом типа. Эти члены действия обыч­но обозначаются глаголами — Read (считать), Write (записать), Flush (очистить), Append (присоединить), Insert (вставить), Remove (удалить) и т. п. Если член, обо­значающий действие, не может выполнить свою задачу, он должен сгенерировать исключение.

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

■ если недостаточно памяти в стеке, генерируется исключение Stack-Overflowlixception\

■ если не удается обнаружить сборку, в которой определен тип, генери­руется исключение PileNotFoundException-,

■ если IL-код метода не поддается верификации, генерируется исключе­ние VetificationException;

■ если недостаточно памяти для JIT-компиляции IL-кода, генерируется исключение OutOJMemoryException.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]