Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Соглашения по оформлению событий  (Прочитано 9306 раз)
0 Пользователей и 1 Гость смотрят эту тему.
yudjin
Помогающий

ua
Offline Offline
Пол: Мужской

« : 23-11-2010 09:27 » 

Заставили задуматься слова Трея Нэша:

Цитата
Существует популярная идиома при генерации события - инициировать его внутри метода protected virtual по имени On<event>... Таким образом, производные классы могут легко модифицировать действия, предпринимаемые, когда должно быть инициировано событие...

Т.е. в виртуальном методе protected virtual OnClick он предлогает вызывать событие при клике мыши, допустим. Но ведь в MFC и в Delphi подобным образом обзывали методы, обрабатывающие события. Ну и я так в дальнейшем поступал: был базовый класс, который инициировал событие там, где нужно, а в protected virtual OnClick была его обработка у дочерних классов.
Так, у меня есть базовый класс Document с методом protected abstract void OnLayerVisiblyChanged(object sender, MapSurrounds.ItemArgs e);. Где-то (допустим, в конструкторе) Document подписывается на событие LayerVisiblyChangedEvent, и когда оно происходит - вызывает метод void OnLayerVisiblyChanged(object sender, MapSurrounds.ItemArgs e). А уже дочерние классы сами решают, что должно происходить в этот момент.

Так вот, решил разобраться. Читаю http://www.rsdn.ru/article/mag/200401/codestyle.XML. Там в разделе "события" пишут то же самое, что и у Трея Нэша:
Код:
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
public class MouseEventArgs : EventArgs
{
  private int x;
  private int y;

  public MouseEventArgs(int x, int y)
  {
    this.x = x;
    this.y = y;
  }

  public int X { get { return x; } }
  public int Y { get { return y; } }
}

Код:
public class Control
{
  public event MouseEventHandler MouseMove;
  protected virtual void OnMouseMove(MouseEventArgs e)
  {//Вызов! А я тут всегда обработку пишу
    if (MouseMove != null)
      MouseMove(this, e);   
  }
}

Не могу понять, как так получилось и как все таки правильно? Почему в On<event> в MFC и в Delphi идет обработка события, а тут предлогают вызывать его.
« Последнее редактирование: 23-11-2010 09:58 от RXL » Записан
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #1 : 23-11-2010 09:47 » 

yudjin, по-моему очевидно, что тебе дается право перехватить, например, OnMouseMove (пользователь двинул мышь влево) и, в зависимости, от твоего желания, выполнить действие:
* подвинуть мышку на форме влево
* не двигать мышку, а нарисовать зеленый кружок Улыбаюсь
* подвинуть мышку вверх (!) и нарисовать кружок

Или я не совсем понял твою мысль?

Может быть, ты путаешь роли - кто должен генерировать событие, а кто обрабатывать?
« Последнее редактирование: 23-11-2010 09:52 от baldr » Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
yudjin
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #2 : 23-11-2010 10:01 » 

baldr, вот именно - я всегда обрабатывал события по своему желанию в методах On<событие>. В примере с RDSN предлагают в подобных методах вызывать эвенты. Но тогда производный класс должен будет почти всегда вызывать base.On<событие>()... Кто генерирует и кто обрабатывает - вроде ясно - кто подписался, тот и обрабатывает Улыбаюсь Тут вопрос скорее оформления...
Вот с помощью IntelleSense если я наследуюсь от класса из Библиотеки базовых классов крутых дядек, то можно видеть кучу protected On<>... И вот вопрос - в этих виртуальных методах принято Вызывать события или Обрабатывать?

Если обрабатывать - тогда логично - производный класс вносит свою логику (где ему какой кружочек рисовать) и сам решает, добавлять ли ему логику базового или нет. Но вот ребята с RDNS почему-то говорят, что нужно Вызывать. Конечно, они для меня не авторитеты )) Но в общем-то, я придерживался (сам того не зная) такого же оформления, как они и описывали. За исключением событий.
« Последнее редактирование: 23-11-2010 10:05 от yudjin » Записан
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #3 : 23-11-2010 10:07 » 

Мне кажется, событие, например, какое-нибудь SomethingChangedEvent может произойти в любом месте - например, при чтении файла или при перерисовке контрола, или даже по таймеру.. В тот момент оно и кидается, а в On<событие> - уже приходит готовый эвент, причем не обязательно его отправил собственный класс.
Так что я с тобой согласен и тоже понимаю этот принцип так же.
Теперь сидим и ждем ответа гуру Улыбаюсь
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 23-11-2010 13:24 » 

Я не гуру, но скажу Улыбаюсь

Пишем код:
Код:
void UsefulAction()
{
  /// blah-blah-blah
  this.OnEvent();
}

Здесь у нас возникает событие, и мы вызываем метод On..., который реализует реакцию на это событие. Реакцией на событие может быть полезный код, переопределённый в производных классах, а может ничего не делаться. Одной из разновидностей полезного кода является реализация pattern'а Observer (Наблюдатель), каковая в .NET реализуется через event'ы, delegate'ы.

Таким образом, лично я не вижу того противоречия, которое заявлено в начале.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
yudjin
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #5 : 23-11-2010 14:28 » 

Dimka, метод this.OnEvent() - вызывает событие? Или обрабатывает входящее событие? Хотя вы пишете, что метод  On... реализует реакцию (читать - обрабатывает входящее событие?) - в среде .NET (если не брать Observer, т.к. этот шаблон достойно реализован event'ами и делегатами) обработку принято добавлять операцией +=. Значит, у вас, похоже, вызывает. И у Нэя. И у ребят из RSDN'a вызывает.
А я (и baldr вроде ка кпризнался) реагирую внутри этих методов на вызовы событий, обрабатываю. И, судя по всему, классы из базовых библиотек .NET'а тоже в методах On<event> обрабатывают события, а не вызывают.
Понятно, что можно в On<event> писать все, что угодно, и свойства называть OnClick, и поля MyEventHandler... Просто интересно, почему одна половина делат Так, а другая Сяк. Про  Observer речь не идет, т.к. этот шаблон достойно реализован event'ами и делегатами.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 23-11-2010 17:54 » 

yudjin, перечитай мною сказанное ещё раз и внимательно. Именно про Observer речь и идёт. Реакцией на событие является его обработка. Обработка заключается в том, чтобы "попинать" переменную, объявленную как event (т.е. перебрать всех подписчиков и уведомить их о наступлении события). Не надо путать событие и event-конструкцию (тоже называемую событием, хотя являющуюся лишь каналом передачи/распространения сообщений о событии). Именно из-за этой путаницы у тебя в голове возникает противоречие, которого на самом деле нет.
« Последнее редактирование: 23-11-2010 18:31 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
yudjin
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #7 : 07-12-2010 15:39 » 

Код:
void UsefulAction()
{
  /// blah-blah-blah
  this.OnEvent();
}
this.OnEvent() - шаблонный метод? Если да, то я вроде понял. И так действительно лучше

C# развращает
« Последнее редактирование: 07-12-2010 15:59 от yudjin » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 07-12-2010 16:06 » 

yudjin, ну если хочется, то можно вместо Observer реализовать Template Method - тогда да.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines