Большинство стоковых событий .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) это было своего рода упражнением по набору текста.
Одна из причин, которая приходит на ум, заключается в том, что вы можете проще возвращать свои значения, когда они упакованы в объект - т.е. обработчик может модифицировать член объекта. Однако в случае многоадресных событий это не всегда может быть хорошо.
Итак, почему?
Причина этого заключается в том, чтобы избежать серьезных изменений. Например, ваш класс может захотеть включить дополнительную информацию в свое событие, однако каждая вещь, которая использовала это событие, будет повреждена, так как делегат больше не будет соответствовать. Имея строгого делегата, ваше событие может инкапсулировать больше информации в будущем, не затрагивая подписчиков.
Редактировать: в соответствии с комментариями я расскажу о том, как это влияет на сокращение критических изменений.
Если мы хотим добавить дополнительную информацию к нашему вызванному событию, используя один класс, полученный из EventArgs
, могут быть добавлены новые свойства / методы. Это будет означать, что любые существующие подписчики на событие не потребуют никаких изменений, так как добавление этих свойств не влияет на них. Единственное требуемое изменение будет в том случае, если эти свойства установлены / использованы, например, где событие поднимается.
Как уже отмечали другие, для этого есть причины ремонтопригодности и согласованности. Подход EventArgs также позволяет обработчику событий изменить EventArgs.
Одной из причин изменения EventArgs является обработка ошибок. Исключение, пойманное где-то в фоновом потоке, передается клиенту как событие. Клиент может установить флаг в EventArgs, чтобы указать, что исключение было обработано, и его не следует перебрасывать в фоновом потоке.
Другим примером является класс ObjectDataSource
, который позволяет клиенту предоставлять экземпляр объекта, когда он требуется. Это делается путем подписки на событие ObjectDataSource.ObjectCreating
и предоставления экземпляра объекта путем установки члена EventArgs.
Во-первых, причина , почему этот шаблон является настолько распространенным (как вы уже спрашивали), заключается в том, что Microsoft специально прописала , поэтому, когда они разработали Шаблон событий (да, они тоже придумали этот термин). Я не обязательно думаю, что это лучше или хуже, чем придумывать собственные подписи делегатов, но следование хорошо известному соглашению может иметь свои преимущества.
По Microsoft:
Тип возврата Void.
Первый параметр называется отправителем и имеет тип Object. Это объект, который вызвал событие.
Второй параметр называется e и имеет тип EventArgs или производный класс EventArgs. Это специфичные для события данные.
Метод принимает ровно два параметра.
Однако, чтобы получить больше информации по вашему вопросу, я думаю, что обоснование использования EventArgs двоякое:
Для получения дополнительной информации см. Дополнительную информацию от Microsoft:
В дополнение к соглашению о обратной совместимости, о котором уже упоминали другие, класс EventArgs обеспечивает больший контроль над непрерывным доступом к параметрам при их передаче более чем одному объекту.
Этот элемент управления может использоваться для того, чтобы сделать определенные значения неизменяемыми, поэтому, если событие отправляется 3 различным подписчикам, вы можете гарантировать, что оно не подделано.
В то же время вы можете предлагать несколько значений [out], и вам не нужно жонглировать возвращаемыми значениями или параметрами [ref], что значительно усложняет процесс многоадресной рассылки. Это также гарантирует, что любая логика проверки происходит в подклассе EventArgs, а НЕ в классе, который генерирует события.