- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
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 CarEventArgs("Осторожно! Могу сломаться!"));
}
…
}
}
С точки зрения вызывающей стороны, все, что нам требуется, так это обновление обработчиков событий, чтобы иметь возможность принять поступающие параметры и получить сообщение через доступное только для чтения поле. Например:
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(), редко бывают предназначены для вызова вне вызываемого делегата. А с точки зрения продуктивности слишком непривлекательно (хотя и не запрещено) вручную определять специальные методы, которые вызываются объектом делегата.
Чтобы разрешить эту проблему, теперь позволяется ассоциировать делегат непосредственно с блоком операторов программного кода при регистрации события. Формально такой программный код называется анонимным методом. В качестве иллюстрации базового синтаксиса рассмотрите следующий метод Main(), в кото-рам посылаемые типом Car события обрабатываются о помощью анонимных методов, а не специальных именованных программ обработки событий.
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);
};
c1.Exploded += delegate(object sender, CarEventArgs e) {
Console.WriteLine("Фатальное сообщение от Car: {0}", e.msg);
};
…
}
}
Замечание. После завершающей фигурной скобки анонимного метода должна следовать точка с запятой. Если пропустить точку с запятой, будет получено сообщение об ошибке компиляции.
Обратите вниманий на то, что тип Program уже не определяет конкретные статические программы обработки событий, такие как, например, CarAboutToBlow() и CarExploded(). Вместо этого здесь указаны безымянные (т.е. анонимные) методы, определяемые "внутристрочно" в тот момент, когда вызывающая сторона обрабатывает событие, используя синтаксис +=.
Базовый синтаксис анонимного метода соответствует следующему представлению в псевдокоде.
class SomeCaller {
static void Main(string[] args) {
SomeType t = new SomeType();
t.SomeEvent += delegate(необязательныеАргументыДелегата) { /* операторы */};
}
}
В предыдущем варианте метода Main() следует обратить внимание на то, что при обработке первого события AboutToBlow мы не определяем аргументы, передаваемые делегатом.
c1.AboutToBlow += delegate {
Console.WriteLine("Ox! Едем слишком быстро!");
};
Строго говоря, получать входные аргументы, посылаемые конкретным событием, не обязательно. Но если вы хотите использовать поступающие аргументы, вы должны указать параметры, прототипы которых заданы типом делегата (как это сделано во втором случае обработки событий AboutToBlow и Exploded). Например:
c1.AboutToBlow += delegate(object sender, CarEventArgs e) {
Console.WriteLine("Важное сообщение от Car: {0}", e.msg);
};
Доступ к "внешним" переменным
Анонимные методы интересны в том отношении, что они позволяют доступ к локальным переменным определяющего их метода. Формально говоря, такие переменные являются "внешними переменными" анонимного метода. Для примера предположим, что наш метод Main() определяет локальную целую переменную-счетчик с именем aboutToBlowCounter. В рамках анонимных методов, обрабатывающих событие AboutToBlow, мы будем увеличивать этот счетчик на 1 и печатать его значение в конце Main().
static void Main(string[] args) {
…
int aboutToBlowCounter = 0;
// Создание машины.
Car c1 = new Car("SlugBug", 100, 10);
// Регистрация обработчиков событий в виде анонимных методов.
c1.AboutToBlow += delegate {
aboutToBlowCounter++;
Console.WriteLine("Ox! Едем слишком быстро!");
};
c1.AboutToBlow += delegate(string msg) {
aboutToBlowCounter++;
Console.WriteLine("Важное сообщение от Car: {0}", msg);
};
…
Console.WriteLine("Событие AboutToBlow вызывалось {0} раз(а).", aboutToBlowCounter);
Console.ReadLine();
}
В результате выполнения этого обновленного метода Main() завершающий оператор Console.WriteLine() сообщит вам о том, что событие AboutToBlow генерировалось дважды.
Замечание. Анонимный метод не имеет возможности получить доступ к параметрам ref и out определяющего метода.
Групповое преобразование методов в C#
Еще одной связанной с делегатами и событиями возможностью в C# является так называемое групповое преобразование методов. Эта возможность позволяет регистрировать "просто" имя обработчика событий. Чтобы пояснить это на примере, мы снова рассмотрим тип SimpleMath, уже рассматривавшийся в этой главе выше, но добавим в него новое событие, которому будет назначено имя ComputationFinished.
public class SimpleMath {
// Здесь мы не утруждаем себя созданием
// производного типа System.EventArgs.
public delegate void MathMessage(string msg);
public event MathMessage ComputationFinished;
public int Add(int x, int y) {
ComputationFinished("Сложение выполнено.");
return х + y;
}
public int Subtract(int x, int y) {
ComputationFinished("Вычитание выполнено.");
return x – у;
}
}
Если не использовать синтаксис анонимных методов, то мы должны обработать событие ComputationComplete так, как показано ниже.
class Program {
static void Main(string[] args) {
SimpleMath m = new SimpleMath();
m.ComputationFinished += new SimpleMath.MathMessage(ComputationFinishedHandler);
Console.WriteLine("10 + 10 равно {0}", m.Add(10, 10));
Console.ReadLine();
}
static void ComputationFinishedHandler(string msg) { Console.WriteLine(msg); }
}
Но можно зарегистрировать программу обработки событий для конкретного события и так, как показано ниже (в остальном программный код изменений не претерпевает).