Подтвердить что ты не робот

Почему аргументы события упаковки в классе, почему?

Большинство событий в .NET имеют следующую подпись:

delegate void SomethingSomething(SomethingEventArgs e);
event SomethingSomething OnSomethingSomething;

и

class SomethingEventArgs
{
    public string Name;
    public int Index;
    public double Groar;
}

Почему это лучше (очевидно, иначе кто-то захочет делать), чем:

delegate void SomethingSomething(string Name, int Index, double Groar);
event SomethingSomething OnSomethingSomething;

так как вам не нужно упаковывать ваши параметры в объект и без инициализаторов (.NET 2.0), это было типичное упражнение.

Одна из причин, которая приходит на ум, состоит в том, что вы можете вернуть свои ценности проще, когда они упакованы в объект - т.е. обработчик может изменять член объекта. Однако при многоадресных событиях это не всегда может быть хорошим.

Итак, почему?

4b9b3361

Ответ 1

Читайте о Принцип Open/Closed.

Используя класс, все унаследованные классы могут ввести дополнительную функциональность, не изменяя подпись делегата. Они могут просто ввести новый класс событий (ExtendedEventArgs), который наследует ваш (SomeEventArgs).

Ответ 2

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

Цитата из Microsoft Код завершен:

Ограничьте количество параметров подпрограмм примерно до семи. Семь магическое число для понимания народов. Психологические исследования обнаружили, что люди обычно не могут отслеживать более семи куски информации сразу (Miller 1956). Это открытие было применяется к огромному числу дисциплин, и кажется безопасным что большинство людей не могут отслеживать более семи рутинные параметры сразу.

На практике, сколько вы можете ограничить количество параметров зависит от того, как ваш язык обрабатывает сложные данные типы. Если вы программируете на современном языке, который поддерживает структурированные данных, вы можете передать составной тип данных, содержащий 13 полей и думать об этом как о ментальном "куске" данных. Если вы программируете более примитивный язык, вам может потребоваться передать все 13 полей отдельно,

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

Цитата из исходного изображения

Ответ 3

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

Изменить: согласно комментариям я расскажу о том, как это влияет на сокращение нарушений.

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

Ответ 4

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

  • EventHandler<T> тип делегата (вам не нужно определять собственный тип делегата).
  • В Reactive Extensions (Rx) есть преобразование события в IObservable<T>, позволяющее использовать LINQ для источников событий с Observable.FromEvent.

Также у вас есть недочеты:

  • Делегат принимает два аргумента: object source и SomethingEventArgs
  • Тип SomethingEventArgs наследует EventArgs.

Таким образом, ваш код должен быть образцом шаблона:

В области пространства имен:

public class SomethingEventArgs : EventArgs {
    public string Name;
    public int Index;
    public double Groar;
}

public delegate void SomethingSomething(object source, SomethingEventArgs e);

и в типе, отображающем тип

public event SomethingSomething OnSomethingSomething;

(Событие также может быть internal.)

Ответ 5

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

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

Другим примером является класс ObjectDataSource, который позволяет клиенту поставлять экземпляр объекта, когда требуется. Это делается путем подписки на событие ObjectDataSource.ObjectCreating и подачи экземпляра объекта путем установки члена EventArgs.

Ответ 6

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

Когда вы передаете экземпляр класса в качестве параметра для метода, он передается по ссылке. Это позволяет экземпляру объекта изменять во время вызова метода. Эти измененные значения затем могут быть прочитаны вызывающим абонентом после возникновения события.

Например:

Посмотрите делегат FormClosingEventHandler (в Windows Forms).

Этот делегат использует параметр типа FormClosingEventArgs.

Если подписчик на событие с использованием этого делегата устанавливает свойство Cancel (унаследованное CancelEventArgs) в true, то форма не закрыта.

Кроме того, эти ответы также верны:

Ответ 7

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

В Microsoft:

  • Тип возврата - Void.

  • Первый параметр называется отправителем и имеет тип Object. Это объект, который поднял событие.

  • Второй параметр имеет имя e и имеет тип EventArgs или производный класс EventArgs. Это данные, специфичные для события.

  • Метод принимает ровно два параметра.

Чтобы получить более точную информацию о вашем вопросе, я думаю, что разумность использования EventArgs двоякая:

  • Таким образом, классы, которые наследуют ваш класс, все равно могут воссоздать событие с производным классом EventArgs.
  • Чтобы классы, обрабатывающие ваше событие, могут использовать общие обработчики событий для обработки нескольких типов событий, даже если разные события используют разные EventArg. Или, если вы измените событие по дороге, любые классы, которые уже обрабатывают событие, не нуждаются в изменении своего кода, потому что обработчики будут по-прежнему совместимы с новым событием.

Подробнее читайте в Microsoft:

Ответ 8

Чтобы следовать .NET стандартам, рекомендуемый способ создания события:

  • Создайте класс, наследующий от EventArgs
  • Использовать общий делегат EventHandler<T>

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

Пример:

public event EventHandler<SometingEventArgs> SomethingEvent;

class SomethingEventArgs 
{     
      public string Name;    
      public int Index;     
      public double Groar; 
}

Ответ 9

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

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

В то же время вы можете предлагать несколько значений [out], и вам не нужно жонглировать возвращаемыми значениями или параметрами [ref], что значительно усложняет процесс многоадресной рассылки. Это также гарантирует, что любая логика проверки выполняется в подклассе EventArgs, а не в классе, который запускает события.