Как события назначаются в .NET - PullRequest
9 голосов
/ 03 июня 2010

Я только что понял, что не до конца понимаю, почему в .NET вы назначаете события, используя символ + =.

Я понял это вчера, когда мне нужно было удалить событие и, не думая, что я делаю

someobject.onsomeevent += null

подумал, что просто удалит событие, которое я ранее назначил.

После некоторого расследования я понял, что должен

someobject.onsomeevent -= someeventmethod;

После выяснения этого я понял, что не понимаю, как методы событий назначаются в .NET.

Итак, у меня есть несколько вопросов:

Во-первых, значит ли это, что я могу сделать

someobject.onsomeevent += someeventmethod;
someobject.onsomeevent += someeventothermethod;

Если так, то при наступлении onsomeevent они оба получат удар, причем в указанном порядке или одновременно?

Кроме того, как определить, какие методы событий уже назначены для someobject.onsomeevent ?

Во-вторых, есть ли способ сохранить методы событий в некотором классе, удалить их из someobject.onsomeevent и переназначить их после завершения некоторых других процедур, которые обычно вызывают событие? *

Ответы [ 5 ]

4 голосов
/ 03 июня 2010

Относительно вашего первого вопроса: вы получаете многоадресное поведение по умолчанию. То есть, если у вас есть несколько обработчиков, то по умолчанию обработчики событий будут вызываться последовательно (если только один из них не вызывает исключение). Обратите внимание, что вы можете изменить add (+=) и remove (-=), чтобы сделать что-то отличное от поведения по умолчанию.

У Джона Скита есть страница, объясняющая делегатов и события в C # , которые вы, возможно, захотите прочитать.

3 голосов
/ 03 июня 2010

Первый вопрос: Да, вы можете сделать это, если сигнатуры метода совместимы с типом делегата события.

Второй вопрос: Да, вы тоже можете это сделать. Используйте EventTest.GetInvocationList(), чтобы зарегистрировать методы для вашего мероприятия. А затем используйте -= и += для удаления и повторного добавления делегатов соответственно. Смотрите пример ниже:

  public class Test 
  {
        public event EventHandler EventTest = delegate { };
        public void Method()
        {
            //get registered event handlers
            Delegate[] invocationList = EventTest.GetInvocationList();

            //remove them
            foreach (Delegate d in invocationList)
            {
                EventTest -= (EventHandler)d;
            }

            //this method won't trigger anything, because 
            //invocation list is empty
            Method2();

            //re-add event handlers
            foreach (Delegate d in invocationList)
            {
                EventTest += (EventHandler)d;
            }
        }

        public void Method2()
        {
            if(EvenTest != null)
            EventTest(this, EventArgs.Empty);
        } 
   }

Я удалил тривиальный Main() -метод, чтобы сделать код более читабельным.

2 голосов
/ 03 июня 2010

И для краткости, я не думаю, что кто-то явно имел дело с событиями, все события не происходят одновременно - они запускаются последовательно ...

2 голосов
/ 03 июня 2010

Делегаты являются «многоадресными» в .NET, а события - как свойства-оболочки. Вы можете получить лучшее понимание, посмотрев на событие в расширенной форме:

private EventHandler _handler;

public event EventHandler MyEvent
{
  add { _handler = (EventHandler)Delegate.Combine(_handler, value);  }
  remove { _handler = (EventHandler)Delegate.Remove(_handler, value); }
}

Обычно вы пишете все вышеперечисленное в 1 строку:

public event EventHandler MyEvent;

И чтобы завершить, событие содержит Invocationlist, который он обрабатывает последовательно при запуске. О заказе нет никаких гарантий.

2 голосов
/ 03 июня 2010

Так что ответ да, да и последовательно в порядке добавления.

Событие является экземпляром класса MulticastDelegate. Чтобы узнать, какие делегаты назначены событию, вызовите метод GetInvocationList для этого события. Смотри http://msdn.microsoft.com/en-us/library/system.multicastdelegate.getinvocationlist%28v=VS.71%29.aspx

Это даст вам массив делегатов. Таким образом, вы можете вызвать GetInvocationList, чтобы получить существующие обработчики событий; затем очистите обработчики событий от события; выполнить какое-то действие; а затем переназначить обработчики обратно на событие.

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