Skip to content

Instantly share code, notes, and snippets.

Created August 27, 2017 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/1db25437707da37ec77ec2f37394536f to your computer and use it in GitHub Desktop.
Save anonymous/1db25437707da37ec77ec2f37394536f to your computer and use it in GitHub Desktop.
Создание события c

Создание события c



Только полноправные пользователи могут оставлять комментарии. TM Feed Хабрахабр Geektimes Тостер Мой круг Фрилансим. Хабрахабр Публикации Пользователи Хабы Компании Песочница. Невозможно, просто взять и вникнуть в этот глубокий смысл, изучая События event в просторах базового и, на первый взгляд, бесконечного C. Когда я изучал События не в рамках. Поэтому, я решил опубликовать свою методику понимания структуры пользовательского события , коим представляется ключевое слово event в С. Не буду цитировать и без того замученную MSDN , а постараюсь объяснить понятно и доступно. Что требуется Вам для изучения: Вы не должны испытывать страх перед изучением. Пожалуйста, читайте медленно и вдумчиво. Вы должны понимать классы и методы. Вы должны знать понимать, что есть делегаты. Хотя, Вы можете попытаться понять их в ходе чтения статьи. Событие , это не что иное, как ситуация, при возникновении которой, произойдет действие или несколько действий. Говоря языком программного моделирования, Событие — это именованный делегат, при вызове которого, будут запущены все подписавшиеся на момент вызова события методы заданной сигнатуры. Итак, Событие , это ситуация, при возникновении которой, произойдут некоторые действия. Само событие имеет определенную структуру. Предположим, что стоит такая задача: Первый класс будет считать до , используя цикл. Проще говоря, при обнаружении значения 71, вызовутся по методу, соответственно для каждого класса. Разложим все по полкам. Подготовим эти три простейших класса, оставив точку входа в программу main нетронутой. Класс ClassCounter и его метод Count в котором будет производится счет. В коде я опускаю пространства имен namespace , ибо это ясно, как день. У каждого по методу, как и договаривались. WriteLine "Пора действовать, ведь уже 71! WriteLine "Точно, уже 71! Теперь вернемся к классу ClassCounter и создадим счетчик при помощи цикла for c переменной-счетчиком int i. У нас есть класс счетчик и два класса, которые будут выводить сообщения. Событие, которое мы хотим создать, будет представлять фразу "… счетчик считает. И как только он будет равен 71, должны выполниться действия". Представим его при помощи условного оператора if. Представляет собой сочетание названия типа, который метод возвращает, плюс название типов входящих параметров по порядку! Например, метод int NewMethod int x, char y будет иметь сигнатуру int int, char , а метод void NewMethod — void void. Как Вы уже поняли, так как наше событие будет ссылаться на два метода void Message , мы должны определить сигнатуру этих методов, и составить на основе этой сигнатуры делегат. Определяем делегат назовем его MethodContainer: Он должен запуститься, когда условие выполнится. Методы, которые вызовет это событие, определены по сигнатурам и на основе их создан делегат. Событие, в свою очередь, создано на основе делегата. Пора показать событию onCount , какие же все-таки методы должны сработать мы ведь указали только их сигнатуру. Вернемся в точку входа программы main и создадим экземпляр класса ClassCounter. А также создадим по экземпляру классов, которые должны запуститься. Они должны быть public. Происходит это следующим образом: Никаких скобочек после метода! Мы же не вызываем его, а просто указываем его название. Теперь осталось запустить счетчик класса ClassCounter и подождать, пока i станет равным Пора действовать, ведь уже 71! Постарайтесь понять смысл и порядок создания события. Определите условие возникновения события и методы которые должны сработать. Определите сигнатуру этих методов и создайте делегат на основе этой сигнатуры. Создайте общедоступное событие на основе этого делегата и вызовите, когда условие сработает. Обязательно где-угодно подпишитесь на это событие теми методами, которые должны сработать и сигнатуры которых подходят к делегату. Если Вы не подписались на событие и его делегат пустой, возникнет ошибка. Чтобы избежать этого, необходимо подписаться, или не вызывать событие вообще, как показано на примере Т. Он создал событие для определенных методов, ограничив их делегатом по определенной сигнатуре. События широко используются для составления собственных компонентов управления кнопок, панелей, и т. У самых маленьких может возникнуть вопрос: Все дело в делегате, на котором базируется событие. А точнее сигнатура подходящих для делегата методов. Естественно, параметр может быть чем угодно. Microsoft упростила задачу конструирования делегатов: NET предлагает готовый делегат EventHandler и т. Ну и не забывайте о практике. Если вы не ни разу не использовали делегаты, лучше попробуйте потренироваться на делегатах, а затем попытайтесь понять эту статью. Я надеюсь, что внес небольшое понимание в эту непростую тему. Программирование 2,9k авторов , 6,5k публикаций. Анализ и проектирование систем авторов , публикация. Java 1,1k авторов , 2,2k публикаций. Разработка игр 1,2k авторов , 2,9k публикаций. Алгоритмы 1,3k авторов , 2,3k публикаций. Разработка под Android 1k авторов , 2,2k публикаций. Разработка мобильных приложений 1k авторов , 2,8k публикаций. Информационная безопасность 2,4k авторов , 6,4k публикаций. JavaScript 1,9k авторов , 4k публикаций. Ненормальное программирование авторов , публикации. Вещи, которые мне надо было знать прежде, чем создавать систему с очередью 4,3k 5. Добавить в закладки Алексей Ковальчук StraySpirit карма. Действительно, для новичков может быть полезно. Там будет все просто, но для новичков это может быть не так то уж и очевидно. Читал статью, а думал больше о проекте текущая задача адовая. Поправьте пожалуйста имена по CamelCase стандарту: А то новичкам такое вредно показывать. Пример, сам по себе, является образцом как не нужно делать, между проверкой и вызовом, может произойти отписывание от события и тогда получим NullReferenceException. Выходов из этой ситуации ровно два. Первый — копируем событие в локальную переменную и работаем с ней, второй — в месте инициализации класса добавляем пустой обработчик для события, исключая ситуацию, когда на него никто не подписан и оно равно null. Полностью солидарен с вашим замечанием. Внесу свои 5 копеек для прояснения ситуации: Многие прогрессивные посоны объявляют события так: Или даже вот так: А может даже так: В таком случае можно использовать в дополнение к проверке на null еще и try catch, чтобы исключить такую возможность. Создание анонимной функции на основе лямбда-выражения и создание на ее основе делегата подходящего типа. Они необходимы в тех случаях, когда программисту незачем париться над именами методов и вызываться они будут, как правило в одном единственном месте. Пустыми круглыми скобками мы сообщаем компилятору, что наш анонимный метод не будет иметь параметров. Анонимные методы всегда имеют тип возврата void. Как правило цепочка события-делегаты-анонимные методы образуют единое звено, применение одного без другого мало чем может быть полезна. Такая нотация очень удобна, не приходится дробить логику класса на дополнительное объявление методов. Верю, новичкам немного сложно привыкнуть к ним. Советую почитать в интернете побольше на данную тематику статей, тема немаленькая, но интересная и очень часто в жизни это может пригодиться. Xored, если Вы начинающий, то лямбда для Вас, скорее всего лишнее. Отлично разжевано для новичков! NET системе именования с On… начинаются названия методов, которые эти самые события генерят, например OnTextChanged генерирует событие TextChanged. Не грех будет добавить что если следовать Framework Guidelines эти самые OnXXX методы должны быть virtual, как минимум protected для не-sealed классов и по возможности не содержать большого кол-ва логики кроме вызова события. А не могли бы вы еще рассказать про возможные утечки памяти при работе с событиями и про то, как с ними бороться? В двух словах не расскажешь, ув. Может этого стоит отдельная статья. Но в двух словах: А они не любят порой разбираться в Вашем коде. Если временный маложивущий объект подпишется на событие долгоживущего объекта и забудет отписаться, то он останется в памяти до сборки долгоживущего. Его будет держать подписка. Это наиболее частый случай утечки. Ну и не забывайте о практике Ну если вы являетесь веб разработчиком, то скорее всего не встретите. Мне на практике не приходилось. Спасибо за статью, для новичков самое оно. Но, считаю, что не раскрыта два важных аспекта: Я писал статью с минимальным погружением в. Ну уж разница между использование и неиспользованием ключевого слова это совсем основа. Иначе вы рассказали не о эвенте а о делегате — в вашем коде можно спокойно убрать все слова event и ничего не изменится. Не путайте базовый C и базовый. NET, основанный на С. Помните, очень важно не только подписываться от событий, но и отписываться потом. События хранят ссылки на объекты подписки и пренебрежение отписыванием делает невозможной работу мусорщика. Часто бывает, что делают одно событие которое живет долго и подписывают на него кучу короткоживущих объектов. Не будете отписываться после вызова — вся эта котовасия начнет вам забивать оперативную память. Либо использовать слабые связи, если невозможно определить, когда нужно отписываться от события www. Тема, пожалуй, полезная, но слишком уж поверхностно раскрыта. В комментариях, в целом все проблемы озвучены: Тут самое главное не написано — в чем, собственно, разница между событием и полем или свойством делегатного типа. Если Вы пишете статью для новичков — пожалуйста, упомянтье о майкросотвовских стандартах для сигнатур и именовании методов, кидающих события и самих событий и приведите код в примерах к этим стандартам. Программист все равно за определенный промежуток времени приобретет свой стиль и научится писать код, как ему удобно или как на его конторе хотят. У каждого в голове за столько лет — свой стандарт. Ключевое слово event — это исключительно фигка C , его к сожалению нету в питоне, джаве, плюсах и многих других меинстримовых языках. Если Вам хотелось рассказать про общий паттерн Observer, то имело смысл отвязаться как от слова event, так и от делегатов, так как анонимных методов тоже много где нет. В таком виде, как оно представлено в посте, оно применимо только для C , поэтому лучше использовать общепринятые соглашения для этого языка. Как показывает практика, мало кому в голову приходит, почему EventHandler имеет такую странную сигнатуру, и зачем он вообще нужен, если есть Action. А ведь он такой не зря, просто его достоинства не слишком очевидны. Это я к чему, настоятельно рекомендовал бы начинающим писать события так, как предложено умными дядьками из Microsoft, а ещё лучше разобраться, почему они так предлагают. Для полноты можно указать ещё одну статью про события, которая уже была на хабре. Да, вот это действительно отличная статья по событиям. Понятная и довольно полная. Если что, то я похвалил не вашу статью, а ту, что приведена в ссылке выше. На мой взгляд, новичку гораздо проще понять события, если вообще забить на эти попытки абстрагирования и просто научиться воспринимать функцию как сущность, с которой можно работать как с обычной переменной — присваивать ее, передавать как аргумент и т. Тем более, что для современного шарпа это понимание важно и практично. Ведь вся суть событий сводится к тому, что функция куда-то передается и потом вызывается уже в том месте. А также многие программисты были бы еще лучше, если бы понимали суть программирования в целом. Так как события в. NET реализованы криво, прогрессивное человечество использует Rx. Решили похвастаться в статье для новичков? А что кривого в событиях C? Опишите чем конкретно недовольно прогрессивное человечество. Опишите чем конкретно недовольно прогрессивное человечество События в. NET являются синтаксическим сахаром для паттерна Observer. Причём сахаром довольно никчемным, потому что упрощения от них чуть, а ограничения весьма существенные. Как правило среди наблюдателей observers и наблюдаемого observable б о льшим сроком жизни областью видимости обладает последний. Это значит, что в их взаимодействии критически важной становится отписка от событий. В противном случае мы сталкиваемся с утечками памяти — подвисанием короткоживущих объектов, которые после своего использования недоступны сборщику мусора, даже если отсутствуют прямые ссылки на них в пользовательском коде поскольку продолжают оставаться неявные ссылки из источника событий. Именно так это сделано в Boost. Правильный синтаксический сахар в C должен был выглядеть так псевдокод: Dispose ; Токен подписки не требует тащить всю дорогу явную ссылку на обработчик, чтобы отписаться. Но в C последнее сделано иначе: HandleSomeEvent; В частности, это значит, что при подписке нельзя так просто взять и использовать лямбды, скажем, обернуть предыдущий вызов: Так вот, в случае правильной реализации паттерна Наблюдатель, менеджеру не надо тащить за собой ссылки на подписчиков или источник событий. Скажем, менеджер получил в конструкторе один раз ссылки на подписчиков и издателя, связал их друг с другом и полностью забыл про них: HandleSomeEvent ; Для того, чтобы отписаться, ему не нужны ни подписчик, ни источник, достаточно безликого поля IDisposable: Dispose ; В случае отписки от событий C всё сильно хуже, зачем-то нужны и подписчик, и издатель: HandleSomeEvent; То есть безосновательно увеличена связность. Выше уже писали про кривой синтаксис возбуждения событий raise events. Не могут на лету комбинироваться и преобразовываться Linq-методами. После такого фундаментального комментария осталось только написать про то, как эти проблемы решены в упомянутом Rx. Они не то чтобы решены, они просто изначально не заложены в дизайн. Как-то мне кажется дизайн приложения хромает. Событие onCount должно бы файриться на каждой итерации цикла со значением i в EventArgs, а уже сами подписчики должны решать, что им с этим чудом делать. Недавно начал изучать C после многих лет на плюсах. И вот, обнаруживаю, что в C существует стандартный механизм сигналов, очень для меня полезный. Но вдруг выясняется, что я не могу просто привязать некий объект к событиям и заставить его отписаться от событий во время его уничтожения без каких-то дополнительных действий, воспользовавшись этим стандартным механизмом. А как же RAII? Видимо, я что-то не понимаю в концепции языка. В каких случаях чаще всего используются события с C? RAII в C реализуется через паттерн Disposable. Для контролируемой отписки а-ля RAII как в boost:: NET удобно использовать в ситуациях, когда время жизни подписчика заведомо не меньше времени жизни источника событий, тогда отписка не нужна. Пускай полежит у меня в избранном. Метки лучше разделять запятой. Сейчас Вчера Неделя Защищаем сайт с помощью ZIP-бомб 28,2k Снимаем и вносим наличные в банкомате с помощью смартфона. Впервые в мире 10,6k Три дня как все кассы в стране должны стать онлайн на самом деле нет 40,3k Интересные публикации Хабрахабр Geektimes. Астробиологи из Эдинбургского университета считают, что жизни на Марсе нет из-за токсичных химических соединений GT. За какие заслуги Kingston любят центры обработки данных? Вещи, которые мне надо было знать прежде, чем создавать систему с очередью. Обработка многократно возникающих SIGSEGV-подобных ошибок. Выбор алгоритма вычисления квантилей для распределённой системы. Как у Словакии украли национальный домен верхнего уровня. Никто не хочет сообщать Apple об уязвимостях iPhone GT. Разделы Публикации Хабы Компании Пользователи Песочница. Информация О сайте Правила Помощь Соглашение Конфиденциальность. Услуги Реклама Тарифы Контент Семинары.


События и делегаты в языке C#


События в C используются повсеместно и многие знакомятся с ними в самом начале изучения этого языка. В этом посте я не буду рассказывать основы и базовые принципы создания событий в C и в. Вместо этого, я расскажу, как создать обобщения generic для событий. К вопросу создания дженерика для событий я пришёл из-за работы над дипломом, где мне нужно создавать много событий, отличающихся только передаваемыми аргументами. При этом, логика их создания и вызова была идентична. Но аргументы могли быть различными, причём в будущем их разнообразие должно только увеличиваться. На помощь пришёл всемогущий Google и всезнающий Рихтер. NET уже содержит обобщение generic для делегата EventHandler. Но TEventArgs должен получаться из EventArgs. Вам нужен отдельный класс, наследуемый от EventArgs для каждого типа объекта, который вы хотите передать с событием. Либо, придётся передавать данные с типом object:. Этот класс работает, но подобный подход приведёт к потерям производительности на постоянном преобразовании типов и, к тому же, затруднит рефакторинг. Создадим класс, наследуемый от EventArgs с обобщённым типом:. Теперь можно создать класс, который будем передавать с событием: Теперь создадим обработчик события используя только что определённый класс SimpleObject или любой другой класс:. Теперь ни что не мешает, не создавая новых классов для аргументов события, передавать в них аргументы с нужными типами. Чтобы сделать передачу параметров потокобезопасной, нужно предварительно добавить ссылку на делегат во временную переменную. Для удобства использования, эту логику можно инкапсулировать в методе-расширении:. К сожалению, метод Volatile. Read доступен только начиная с. Из-за этого его не получится использовать при разработке на Unity3d , так как он до сих пор использует старую версию Mono, совместимую только с. По старой доброй традиции, публикую архив с работающим примером кода. Aleksei Penzentcev IT по-своему. Read ref eventDelegate ;. К сожалению я не работал с API Mail. Подскажите пожалуйста как вычислить hash md5 на мэйле? Забыл сказать про жильё. Стоимость квартир в Чехии сопоставима с ценами в российских городах-миллионниках типа Самары. Но ипотеку дают под… lexpenz: Остаться в Чехии реально и не оканчивая местного университета. С ним просто немного легче. Извините за беспокойство, хотела бы уточнить насколько реально после университета Масарика остаться жить и работать в Чехии? Mac долгоиграющая рабочая машина не имеющая никаких лагов. Можно до бесконечности спорить, что лучше, но суть не измениться. Ludozhka , вот этот самый простой способ и описан в статье: Только без создания лишних сущностей. Новое RxSwift в примерах. Часть II—наблюдаемое и привязка RxSwift в примерах. Архивы Январь Ноябрь Октябрь Апрель Март Февраль Февраль Январь Декабрь Ноябрь Сентябрь Май Март Февраль Январь Ноябрь Июнь Март Ноябрь Октябрь Сентябрь Апрель Март Февраль Январь Декабрь Ноябрь Октябрь Август Июль Июнь Апрель Март Февраль Январь Декабрь Ноябрь Октябрь Сентябрь


Подольск юбилейная 11 на карте
https://gist.github.com/965980ed5e961b2b4b18ab1d995ebf63
Учреждение приказа тайных дел год
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment