Обоснование класса EventArgs

Я изучаю события на С# и понимаю, что класс EventArgs содержит данные о событии. Но мне трудно понять, почему EventArgs необходимо.

Например, в этот пример MSDN не мог класс WakeMeUp прочитать все необходимые данные (snoozePressed, nrings) из полей AlarmClock? Если он может их установить, почему он не может их получить?

Ответ 1

Углы с классом EventArgs (как я вижу) в основном эти два:

  • Вы можете добавлять участников в класс EventArgs, изменяя подпись события
  • Отключить информацию, переданную обработчику событий из экземпляра объекта

Возможно, даже информация, содержащаяся в EventArgs, не отображается объектом, воссоздающим событие.

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

Ответ 2

Класс EventArgs необходим, потому что если вы хотите продлить свое событие, чтобы предоставить больше информации в будущем, у вас возникли проблемы с переносимостью для всех клиентов, использующих оригинальную сигнатуру метода исходного события.

Например,

public void IHandleEventVersion1(string p1, int p2)
{
    ....
}

Теперь вы хотите предоставить дополнительную информацию в событии EventVersion1 выше (вы хотите включить char). Затем вам придется заставить клиента переписать обработку своих событий так, чтобы они соответствовали вашим новым требованиям:

public void IHandleEventVersion1(string p1, int p2, char p2)
{
    ...
}

Посмотрите, как это может быть неудобно при попытке предоставить дополнительную информацию?

Таким образом, класс EventArgs предоставляет общий шаблон проектирования для программирования, позволяя вам и мне быстро расширять данные, которые мы хотим предоставить для события.

Общая схема кодирования создающей события структуры такова:

Основная стратегия обработки событий

  • Определите event, который пользователи вашего класса могут подписаться на
  • Определите подпись delegate, которую объявляет событие (да, вы также можете использовать стандартную версию .NET 2.0 EventHandler, а именно EventHandler<TEventArgs>)
  • Предоставить метод protected virtual для переопределения наследников в ответ на событие, возникающее в вашем базовом классе
  • В базовом классе, объявляющем ваше событие, укажите базовую реализацию метода protected, в котором вы действительно поднимаете событие.

    public class MyClass
    {
        public event EventHandler  /* (point 2) */ MyEvent; /* (point 1) */
    
        // (point 3 + 4)
        protected virtual void OnMyEvent()
        {
            EventHandler temp = MyEvent;
            if (temp != null)
                temp(this, EventArgs.Empty);
        }
    
        public void SomeMethodThatWillRaiseTheEvent()
        {
            ....
            OnMyEvent();
        }
    }
    

Ответ 3

EventArgs полезен для:

  • показывает состояние в момент времени, в котором произошло событие
  • повышение производительности вашего кода обработки событий путем предоставления информации о событии без необходимости запрашивать "стороннюю сторону"
  • содержащий данные, которые не отображаются объектом, восходящим к событию

Чтобы развернуть первую точку.... между вашим обработчиком событий и вы считываете состояние из объекта, который поднял событие, могли произойти другие вещи, которые полностью изменили состояние на что-то другое. В этом случае вы будете реагировать, например, на событие AlarmHasGoneOff на AlarmClock, где сигнал тревоги уже отключен.

Также возможно реагировать на события, которые были подняты "где-то еще" - быть в другом процессе /appdomain/process на другой машине с помощью различных механизмов. Если вам нужно было перезвонить в "где-то еще", чтобы получить требуемую информацию, это может занять несколько секунд (или меньше или больше!), Что делает передачу полезных/требуемых данных через EventArgs или производный класс массивной производительностью улучшение.

Ответ 4

Данные, переданные в EventArgs, необязательно доступны в свойствах объекта, сгенерировавшего событие. Например, в событии MouseDown MouseEventArgs содержит информацию о текущей позиции мыши. Объект, который сгенерировал это событие, вероятно, даже не сохраняет ничего такого изменчивого.

Ответ 5

Вам не нужно передавать EventArgs.Empty обработчику. Вы можете передать любой производный класс. Когда обработчик события указан для принятия EventArgs в качестве параметра, это означает, что нет никаких конкретных аргументов, которые всегда доступны, но вы можете захотеть передать свои данные для дополнительной информации.

Ответ 6

Еще одна приятная вещь, которую вы получаете от стандартного шаблона, - это то, что люди, использующие ваш класс, который предоставляет событие, могут подключать обычные обработчики событий:

public SomeWinFormClass() { 
  InitializeComponent();
  _yourClassInstance = new YourClass();
  someButton.Click += SomethingICareAboutHappened;
  _yourClassInstance.YourEvent += SomethingICareAboutHappened;
}

private void SomethingICareAboutHappened(object sender, EventArgs e)
{
  // do something -- logging, signaling a handle someone 
  // waiting for, etc.
}

Не нужно также объявлять, что все ваши собственные делегаты объявляют ваши события. Если вы использовали EventHandler<TEventArgs> для объявления YourEvent, я не думаю, что вам это удастся, хотя кажется, что вы должны быть в состоянии.