public class CarEventArgs: EventArgs
public readonly string msg;
public CarEventArgs(string message) {
msg = message;
}
}
Теперь мы должны обновить делегат CarEventHandler так, как показано ниже (события должны остаться без изменений).
public class Car {
public delegate void CarEventHandler(object sender, CarEventArgs e)
…
}
При генерировании событий из метода Accelerate мы теперь должны предоставить ссылку на текущий объект Car (с помощью ключевого слова Car)
и экземпляр нашего типа CarEventArgs.public void Accelerate(int delta) {
// Если машина сломалась, генерируется событие Exploded.
if (carIsDead) {
if (Exploded != null) Exploded(this, new CarEventArgs("Извините, машина сломалась…"));
else {
…
AboutToBlow(this, new
}
…
}
}
С точки зрения вызывающей стороны, все, что нам требуется, так это обновление обработчиков событий, чтобы иметь возможность принять поступающие параметры и получить сообщение через доступное только для чтения поле. Например:
public static void CarAboutToBlow(object sender, CarEventArgs e) { Console.WriteLine ("{0} сообщает: {1}", sender, e.msg); }
Если получатель желает взаимодействовать с объектом, отправившим событие, следует выполнить явное преобразование System.Object. Так, если нужно выключить радио, когда объект Car уже на полпути к своему создателю, можно предложить обработчик событий, который будет выглядеть примерно так.
public static void CarIsAlmostDoomed(object sender, CarEventArgs e) {
// Просто для гарантии здесь перед вызовом предлагается
// проверка среды выполнения.
if (sender is Car) {
Car с = (Car)sender;
c.CrankTunes(false);
}
Console.WriteLine("Важное сообщение от {0}: {1}", sender, e.msg);
}
Исходный код.
Проект PrimAndProperCarEvenfs размещен в подкаталоге, соответствующем главе 8.Анонимные методы в C#
В завершение этой главы мы рассмотрим некоторые связанные с делегатами и событиями возможности .NET 2.0 через призму возможностей C#. Для начала обратим внимание на то, что в случае, когда вызывающей стороне требуется осуществлять прием поступающих событий, необходимо определить уникальный метод, отвечающий виду соответствующего делегата.
class SomeCaller {
static void Main(string[] args) {
SomeType t = new SomeType;
t.SomeEvent += new SomeDelegate(MyEventHandler);
}
// Как правило, вызывается только объектом SomeDelegate.
public static void MyEventHandler {…}
}
Если немного подумать, то станет ясно, что такие методы, как MyEventHandler, редко бывают предназначены для вызова вне вызываемого делегата. А с точки зрения продуктивности слишком непривлекательно (хотя и не запрещено) вручную определять специальные методы, которые вызываются объектом делегата.
Чтобы разрешить эту проблему, теперь позволяется ассоциировать делегат непосредственно с блоком операторов программного кода при регистрации события. Формально такой программный код называется
class Program {
static void Main(string[] args) {
Console.WriteLine("***** Анонимные методы *****\n");
Car c1 = new Car("SlugBug", 100, 10);
// Регистрация обработчиков событий с помощью
// анонимных методов.
c1.AboutToBlow += delegate {
Console.WriteLine("Оx! Едем слишком быстро!");
};
c1.AboutToBlow += delegate(object sender, CarEventArgs e) {
Console.WriteLine("Сообщение от Car: {0}", e.msg);