TestEvent a = new TestEvent(Callback1); // сначала создать делегата
tester.testEvent += a; //
затем добавить его
tester.testEvent += new Test(CallBack2); // или можно сделать это
// за один проход
tester.testEvent += new Test(Callback3);
tester.testEvent += new Test(Callback4);
tester.Perform;
}
public void CallBack1 {
// уведомить через e-mail)
}
public void CallBack2 {
// послать факсы
}
public void CallBack3 {
// послать беспроводное сообщение
}
public void CallBack4 {
// сохранить в журнале
}
}
}
Как можно понять из приведенного примера, чтобы использовать события класса, необходимо сначала получить метод в классе подписчиков для обработки события (очень похоже на то, как действуют делегаты), затем добавить методы обработки события в событие. Давайте создадим статический метод
Notify
:
public static void Notify(string i) {
Console.WriteLine(i);
}
Этот метод использует такую же сигнатуру, что и приемник событий класса
Properties
. В методе
Main
можно зарегистрировать метод
Notify
и задать условно ошибку, чтобы протестировать событие:
Properties props = new Properties("hello"); // зарегистрировать обработчик событий
props.ExceptionEventListener += new ExceptionEventListener(test);
p["Aged"] = "35"; // неправильный ключ используется
// для моделирования ошибки
Исключения
Исключения в C# на первый взгляд являются такими же, как в Java. Инструкции C#
try-catch
и
try-catch-finally
работают подобно своим аналогам в Java (смотрите раздел о ключевых словах). Однако в C# нельзя использовать инструкцию
throws
, поэтому невозможно указать вызывающей стороне, что некоторый код в методе может порождать исключение. Также имеется
try-finally
, который не подавляет порожденные исключения, но предлагает блок
finally
, выполняющий после порождения исключения, чтобы произвести очистку.
Порождение исключений делается с помощью инструкции
throw
. Например, чтобы
породить
SystemException
, используется код
throw new SystemException (<arg-list>);
. Это полностью совпадает c тем, как исключения порождается в Java. Требуется только инструкция
throws
и подходящий класс исключения. Далее представлен список некоторых стандартных классов исключений, предоставляемых средой выполнения .NET. Так же как в Java, их функциональность отражается в данных им именах:
□
Exception
— базовый класс для всех объектов исключений.
□
SystemException
— базовый класс для всех ошибок, создаваемых во время выполнения.
□
IndexOutOfRangeException
возникает, когда индекс массива во время выполнения оказывается вне границ заданного диапазона.
□
NullReferenceException
порождается, когда во время выполнения ссылаются на
null
.
□
InvalidOperationException
порождается некоторыми методами, когда вызов метода бывает не действителен для текущего состояния объекта.
□
ArgumentException
— базовый класс всех исключений для аргументов.
□
ArgumentNullException
порождается если аргумент задан как
null
, когда это недопустимо.
□
InteropException
является базовым классом для исключений, которые возникают или направлены на среды вне CLR.
Одним исключением, которое возникает независимо от того, будет ли оно специально порождаться или нет, является
System.OverflowException
, связанное с вычисленными результатами, превосходящими диапазон значений типа данных переменной результата. Инструкции
checked
и
unchecked
могут инициировать или подавлять связанные с этим исключения. Дополнительная информация о
checked
и
unchecked
находится в разделе данного приложения о ключевых словах.
Условная компиляция
Препроцессор в C# эмулируется. Он выполняется как отдельный процесс, прежде чем компилятор начнет свою работу. Поддерживаемые здесь директивы больше всего соответствуют C++, чем какому-либо другому языку. Конечно, в Java не существует эквивалентов функциональности, описанных в этом разделе. Разрешается определять символы, которые проверяются с помощью простых условных директив. Те, которые оказываются
true
, включаются и компилируются, иначе код игнорируется. Определение символа может происходить двумя способами. Прежде всего с использованием ключа компилятора
/define
, за которым следует двоеточие и определяемый символ, например:
csc /define:TEST_TEST samples.cs
Можно также определить символы на странице конфигурационных свойств проекта, добавляя их в разделенный двоеточиями список констант условной компиляции. Или пойти программным путем, используя директиву
#define
. В этом случае директива должна появиться раньше, чем что-либо другое, и применяется ко всем лексемам в области действия файла. Здесь перечислены допустимые условные директивы: