Полное руководство. С# 4.0
Полное руководство. С# 4.0 читать книгу онлайн
В этом полном руководстве по C# 4.0 — языку программирования, разработанному специально для среды .NET, — детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки.Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.
В данной книге вы найдете:- Полное описание средств языка C#- Подробное рассмотрение новых средств в версии C# 4.0, в том числе PLINQ, библиотеку TPL, именованные и необязательные аргументы, динамический тип данных и многое другое- Сотни простых и понятных примеров программ с комментариями.- Самый полный источник информации по C#Благодаря поддержке параллельного языка интегрированных запросов (PLINQ) и библиотеки распараллеливания задач (TPL) версия 4.0 стала новой вехой в программировании на C#, и поэтому Герберт Шилдт, автор лучших книг по программированию, обновил и расширил свое классическое руководство, чтобы охватить в нем эти и другие нововведения. В книге подробно описываются языковые средства C#, даются профессиональные рекомендации и приводятся сотни примеров программ, охватывающих все аспекты программирования на C#, включая синтаксис, ключевые слова и основные библиотеки, не говоря уже о таких новшествах, как PLINQ, TPL, динамический тип данных, а также именованные и необязательные аргументы.Это необходимое каждому программирующему на C# справочное руководство написано простым и доступным языком, благодаря которому Герберт Шилдт стал таким популярным. В книге найдут ответы на насущные вопросы по C# как начинающие, так и опытные программисты.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
В эту форму входят два аксессора событий: add и remove. Аксессор add вызывается,когда обработчик событий добавляется в цепочку событий с помощью оператора +=.В то же время аксессор remove вызывается, когда обработчик событий удаляется изцепочки событий с помощью оператора -=.
Когда вызывается аксессор add или remove, он принимает в качестве параметрадобавляемый или удаляемый обработчик. Как и в других разновидностях аксессоров,этот неявный параметр называется value. Реализовав аксессоры add или remove,можно организовать специальную схему хранения обработчиков событий. Например,обработчики событий можно хранить в массиве, стеке или очереди.
Ниже приведен пример программы, демонстрирующей аксессорную форму события. В ней для хранения обработчиков событий используется массив. Этот массивсостоит всего из трех элементов, поэтому в цепочке событий можно хранить одновременно только три обработчика.// Создать специальные средства для управления списками// вызова обработчиков событий.using System;// Объявить тип делегата для события.delegate void MyEventHandler();// Объявить класс для хранения максимум трех событий.class MyEvent { MyEventHandler[] evnt = new MyEventHandler[3]; public event MyEventHandler SomeEvent { // Добавить событие в список. add { int i; for(i=0; i < 3; i++) if(evnt[i] == null) { evnt[i] = value; break; } if (i == 3) Console.WriteLine("Список событий заполнен."); } // Удалить событие из списка. remove { int i; for(i=0; i < 3; i++) if(evnt[i] == value) { evnt[i] = null; break; } if (i == 3) Console.WriteLine("Обработчик событий не найден."); } } // Этот метод вызывается для запуска событий. public void OnSomeEvent() { for(int i=0; i < 3; i++) if(evnt[i] != null) evnt[i](); }}// Создать ряд классов, использующих делегат MyEventHandler.class W { public void Whandler() { Console.WriteLine("Событие получено объектом W"); }}class X { public void Xhandler() { Console.WriteLine("Событие получено объектом X"); }}class Y { public void Yhandler() { Console.WriteLine("Событие получено объектом Y"); }}class Z { public void Zhandler() { Console.WriteLine("Событие получено объектом Z"); }}class EventDemo5 { static void Main() { MyEvent evt = new MyEvent(); W wOb = new W(); X xOb = new X(); Y yOb = new Y(); Z zOb = new Z(); // Добавить обработчики в цепочку событий. Console.WriteLine("Добавление событий. "); evt.SomeEvent += wOb.Whandler; evt.SomeEvent += xOb.Xhandler; evt.SomeEvent += yOb.Yhandler; // Сохранить нельзя - список заполнен. evt.SomeEvent += zOb.Zhandler; Console.WriteLine(); // Запустить события. evt.OnSomeEvent(); Console.WriteLine(); // Удалить обработчик. Console.WriteLine("Удаление обработчика xOb.Xhandler."); evt.SomeEvent -= xOb.Xhandler; evt.OnSomeEvent(); Console.WriteLine(); // Попробовать удалить обработчик еще раз. Console.WriteLine("Попытка удалить обработчик " + "xOb.Xhandler еще раз."); evt.SomeEvent -= xOb.Xhandler; evt.OnSomeEvent(); Console.WriteLine(); // А теперь добавить обработчик Zhandler. Console.WriteLine("Добавление обработчика zOb.Zhandler."); evt.SomeEvent += zOb.Zhandler; evt.OnSomeEvent(); }}
Ниже приведен результат выполнения этой программы:Добавление событий.Список событий заполнен.Событие получено объектом WСобытие получено объектом XСобытие получено объектом YУдаление обработчика xOb.Xhandler.Событие получено объектом WСобытие получено объектом YПопытка удалить обработчик xOb.Xhandler еще раз.Обработчик событий не найден.Событие получено объектом WСобытие получено объектом YДобавление обработчика zOb.Zhandler.Событие получено объектом WСобытие получено объектом XСобытие получено объектом Y
Рассмотрим данную программу более подробно. Сначала в ней определяется делегат обработчиков событий MyEventHandler. Затем объявляется класс MyEvent. В самом его начале определяется массив обработчиков событий evnt, состоящий из трехэлементов.MyEventHandler[] evnt = new MyEventHandler[3];
Этот массив служит для хранения обработчиков событий, добавляемых в цепочкусобытий. По умолчанию элементы массива evnt инициализируются пустым значением (null).
Далее объявляется событие SomeEvent. В этом объявлении используется приведенная ниже аксессорная форма оператора event.public event MyEventHandler SomeEvent { // Добавить событие в список. add { int i; for(i=0; i < 3; i++) if(evnt[i] == null) { evnt[i] = value; break; } if (i == 3) Console.WriteLine("Список событий заполнен."); } // Удалить событие из списка. remove { int i; for(i=0; i < 3; i++) if(evnt[i] == value) { evnt[i] = null; break; } if (i == 3) Console.WriteLine("Обработчик событий не найден."); }}
Когда в цепочку событий добавляется обработчик событий, вызывается аксессорadd, и в первом неиспользуемом (т.е. пустом) элементе массива evnt запоминаетсяссылка на этот обработчик, содержащаяся в неявно задаваемом параметре value. Еслив массиве отсутствуют свободные элементы, то выдается сообщение об ошибке. (Разумеется, в реальном коде при переполнении списка лучше сгенерировать соответствующее исключение.) Массив evnt состоит всего из трех элементов, поэтому в нем можносохранить только три обработчика событий. Когда же обработчик событий удаляетсяиз цепочки событий, то вызывается аксессор remove и в массиве evnt осуществляетсяпоиск ссылки на этот обработчик, передаваемой в качестве параметра value. Еслиссылка найдена, то соответствующему элементу массива присваивается пустое значение (null), а значит, обработчик удаляется из цепочки событий.
При запуске события вызывается метод OnSomeEvent(). В этом методе происходитциклическое обращение к элементам массива evnt для вызова по очереди каждого обработчика событий.
Как демонстрирует рассматриваемый здесь пример программы, механизм храненияобработчиков событий нетрудно реализовать, если в этом есть потребность. Но для большинства приложений более подходящим оказывается используемый по умолчанию механизм хранения обработчиков событий, который обеспечивает форма оператора eventбез аксессоров. Тем не менее аксессорная форма оператора event используется в особыхслучаях. Так, если обработчики событий необходимо выполнять в программе в порядкеих приоритетности, а не в том порядке, в каком они вводятся в цепочку событий, то для иххранения можно воспользоваться очередью по приоритету.
ПРИМЕЧАНИЕВ многопоточных приложениях обычно приходится синхронизировать доступ к аксессорам событий. Подробнее о многопоточном программировании речь пойдет в главе 23.Разнообразные возможности событий
События могут быть определены и в интерфейсах. При этом события должныпредоставляться классами, реализующими интерфейсы. События могут быть такжеопределены как абстрактные (abstract). В этом случае конкретное событие должнобыть реализовано в производном классе. Но аксессорные формы событий не могутбыть абстрактными. Кроме того, событие может быть определено как герметичное(sealed). И наконец, событие может быть виртуальным, т.е. его можно переопределить в производном классе.Применение анонимных методов и лямбда-выражений вместе с событиями
Анонимные методы и лямбда-выражения особенно удобны для работы с событиями, поскольку обработчик событий зачастую вызывается только в коде, реализующеммеханизм обработки событий. Это означает, что создавать автономный метод, как правило, нет никаких причин. А с помощью лямбда-выражений или анонимных методовможно существенно упростить код обработки событий.
Как упоминалось выше, лямбда-выражениям теперь отдается большее предпочтение по сравнению с анонимными методами, поэтому начнем именно с них. Нижеприведен пример программы, в которой лямбда-выражение используется в качествеобработчика событий.// Использовать лямбда-выражение в качестве обработчика событий.using System;// Объявить тип делегата для события.delegate void MyEventHandler (int n);// Объявить класс, содержащий событие.class MyEvent { public event MyEventHandler SomeEvent; // Этот метод вызывается для запуска события. public void OnSomeEvent(int n) { if (SomeEvent != null) SomeEvent(n); }}class LambdaEventDemo { static void Main() { MyEvent evt = new MyEvent(); // Использовать лямбда-выражение в качестве обработчика событий. evt.SomeEvent += (n) => Console.WriteLine("Событие получено. Значение равно " + n); // Запустить событие. evt.OnSomeEvent(1); evt.OnSomeEvent(2); }}