Каковы эффекты добавления EventHandler + = EventHandler? - PullRequest
3 голосов
/ 08 июля 2011

У меня есть событие SelectionChanged в классе A, которое я хочу передать через класс B. Я предполагал, что объявление события SelectionChanged в классе B и назначение этого EventHandler для A.SelectionChanged приведет к запуску B.SelectionChanged всякий раз, когдаA.SelectionChanged сработало - это оказалось ложным.

Чтобы быть более понятным, некоторый код:

class A
{
   public event EventHandler SelectionChanged;

   public void TriggerSelectionChanged()
   {
      if (SelectionChanged != null) SelectionChanged(this, EventArgs.Empty);
   }
}

class B
{
   private A _a = new A();

   public A A { get { return _a; } }

   public event EventHandler SelectionChanged;

   public B()
   {
      A.SelectionChanged += SelectionChanged;
   }

   public static void Test()
   {
      B relayer = new B();
      bool wasRelayed = false;
      relayer.SelectionChanged += delegate { wasRelayed = true; };
      relayer.A.TriggerSelectionChanged();

      System.Console.WriteLine("Relayed: {0}", wasRelayed);
   }
}

Это выводит "Relayed: false".

Каковы эффекты добавления EventHandler к другому EventHandler?

РЕДАКТИРОВАТЬ: Примечание!Мне известно, что решением этой проблемы является передача события через делегата, функцию и т. Д. И т. Д., Но я в основном заинтересован в том, чтобы узнать, каков эффект этого кода.

Ответы [ 3 ]

2 голосов
/ 08 июля 2011

В этом случае B SelectionChanged и A SelectionChanged не связаны.

Если вы сделаете так, чтобы B наследовал от A и удалили второе объявление на B, тогда это сработало бы.

class A
{
   public EventHandler SelectionChanged;

   public void TriggerSelectionChanged()
   {
      if (SelectionChanged != null) SelectionChanged(this, EventArgs.Empty);
   }
}

class B : A
{
   public static void Test()
   {
      B relayer = new B();
      bool wasRelayed = false;
      relayer.SelectionChanged += delegate { wasRelayed = true; };
      relayer.TriggerSelectionChanged();

      System.Console.WriteLine("Relayed: {0}", wasRelayed);
   }
}

Или вы можете прокачать свои сообщения через ...

class A
{
   public EventHandler SelectionChanged;

   public void TriggerSelectionChanged()
   {
      if (SelectionChanged != null) SelectionChanged(this, EventArgs.Empty);
   }
}

class B
{
   public B()
   {
     this._a.SelectionChanged += (o, s) => 
     {
       if(this.SelectionChanged != null) { this.SelectionChange(o, s); }
     };
   }




private A _a = new A();

   public A A { get { return _a; } }

   public EventHandler SelectionChanged;

   public static void Test()
   {
      B relayer = new B();
      bool wasRelayed = false;
      relayer.SelectionChanged += delegate { wasRelayed = true; };
      relayer.A.TriggerSelectionChanged();
      System.Console.WriteLine("Relayed: {0}", wasRelayed);
   }

}

2 голосов
/ 08 июля 2011

В вашем коде нет ничего, что "связывало бы" вызов B.SelectionChanged с A.SelectionChanged. Поэтому, когда вы запускаете SelectionChanged на A, ваш делегат, который обрабатывает SelectionChanged на B, не вызывается.

Я думаю, что вы хотите, чтобы ваше событие на B действовало в качестве адаптера на событие, которое выставляет A? Если это так, вам нужно написать собственную логику add / remove. Смотрите следующее:

События + шаблон адаптера

Еще один пример добавления / удаления:

C #: событие с подробностью добавить / удалить! = Типичное событие?

1 голос
/ 08 июля 2011

Оказывается, это результат того, что EventHandler является делегатом. Этот класс реализует оператор + = through (или, я так полагаю), используя Delegate.Combine . Документация этой функции гласит

Объединяет списки вызовов указанных многоадресных (комбинируемых) делегатов.

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

...