Это плохая форма для класса C #, чтобы подписаться на свои собственные опубликованные события? - PullRequest
11 голосов
/ 27 октября 2010

Возможно, я просто невротик, но я регулярно нахожусь в ситуациях, когда у меня есть класс, который публикует событие, и я нахожу удобным подписаться на это событие внутри самого класса (например, в конструкторе),а не только подписка на внешние уроки.

Для меня это звучит разумно, но я не могу избавиться от мучительного ощущения, что это плохая практика, по той простой причине, что я всегда сталкиваюсь с вопросом: "Почему бы не выполнить действия, которые вы бы предоставили в обработчике события в коде, который запускает событие? "

public class Button
{
   public Button()
   {
      this.Click += someHandler; // bad practice?
   }

   public event EventHandler Click;

   public void HandleInput()
   {
      if (someInputCondition)
      {
         // Perform necessary actions here rather than 
         // subscribing in the constructor?
         this.Click(this, ...);
      }
   }
}

Есть ли какие-либо недостатки в подписке на ваши собственные события?

Ответы [ 6 ]

8 голосов
/ 27 октября 2010

Это звучит разумно для меня, но я не могу избавиться от мучительного чувства, что это плохая практика, по той простой причине, что я всегда сталкиваюсь с вопросом: «Почему бы не выполнить действия, которые вы»d предоставить в обработчике события код, который вызывает событие? "

Чтобы ответить на этот вопрос, рассмотрим частичные сценарии классов.Предположим, у вас есть базовый тип B. Вы запускаете автоматизированный инструмент, который декорирует B, расширяя его до производного класса D. Ваш инструмент генерирует частичный класс, чтобы разработчики, использующие D, могли дополнительно настроить его для своих собственных целей.

В этом случае кажется совершенно разумным, что пользовательская сторона D захочет зарегистрироваться для вызова, когда события, объявленные B или машинная сторона D, генерируются машинной стороной D.

Это был сценарий, в котором мы оказались при проектировании ВСТО много лет назад.Как оказалось, это не было сложно сделать в C #, но было довольно сложно заставить все это работать в VB.Я полагаю, что VB внесла некоторые изменения в свою модель подписки на события, чтобы упростить это.

Тем не менее, если бы вы могли избежать этого, я бы сделал это.Если вы просто делаете мероприятие для внутренней подписки, которое кажется плохим запахом кода.Частичные методы в C # 3 очень помогают здесь, так как они позволяют простой и недорогой стороне, генерируемой машиной, вызывать небольшие функции уведомлений на стороне, генерируемой пользователем, без необходимости публиковать событие.

5 голосов
/ 27 октября 2010

Я не вижу проблем с этим. Но если вы обрабатываете события в том же классе, вы также можете переопределить метод события:

protected override void OnClick(Eventargs e)
{
   base.OnClick(e);
}

Это более эффективно и дает вам возможность проглотить событие при необходимости (просто не вызывая base.OnClick ()).

2 голосов
/ 27 октября 2010

Существует очень экзотическая проблема из-за внутренней оптимизации при этом.Из-за оптимизации добавление / удаление обработчиков событий не является потокобезопасным.Это относится только к событиям, которые используются декларирующим типом, как в вашем примере.

К счастью, это было изменено в 4.0, но если вы используете предыдущую версию, вы можете испытать это.

1 голос
/ 27 октября 2010

Если ваш класс кнопок должен быть первым, который получает событие click, вы должны написать свой код в методе события, например:Получатель, вы можете подписаться на событие в обычном режиме.

1 голос
/ 27 октября 2010

Проблема в том, что someHandler изменит состояние вашего объекта. Вы хотите, чтобы это состояние изменилось до или после запуска какого-либо «внешнего» кода событием?

Неясно, в какой момент произойдет изменение состояния, если вы подпишетесь на событие, однако, вызывая его в «HandleInput ()», будет намного понятнее, когда оно будет вызвано.

(Также более нормально вызывать «HandleInput ()», «OnClick» и делать его виртуальным, чтобы подклассы могли его переопределять)

Сказав вышесказанное, обычно нет большого вреда в подписке на собственное событие; в классах пользовательского интерфейса, которые представляют формы, это очень распространено, в противном случае это, как правило, «удивляет» многих людей, которые читают ваш код.

0 голосов
/ 27 октября 2010

, если взять в качестве примера обычный класс System.Windows.Form,
когда вы хотите обработать событие Form_Load (с помощью визуального дизайнера студии), оно обрабатывается в классе самой формы!

this.Load += new System.EventHandler(this.Form1_Load);

 private void Form1_Load(object sender, EventArgs e)
 {
 }

так что я думаю, что это вообще не проблема !!.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...