Преимущества событий с использованием EventArgs / EventArgs <T>типов делегатов вместо… - PullRequest
5 голосов
/ 29 июня 2010

Я понимаю преимущества событий, использующих типы делегатов с подписью delegate void delegate_name(object sender, EventArgs e)

a) Но кроме того факта, что это может сэкономить нам некоторую типизацию, есть и другие причины, по которым мы должны использовать уже определенные типы делегатовEventHandler/EventHandler<T> вместо того, чтобы объявлять наши собственные типы делегатов с подписью delegate void delegate_name(object sender, EventArgs e)?

b) Есть две другие причины использования предопределенных типов делегатов EventArgs/EventArgs<T>:

  • люди, потребляющие определенное событие (скажем, event EventHandler my_event), сразу узнают, как использовать это событие?

  • возможно, некоторые популярные сторонние методы принимают в качестве параметров EventHandler/ EventHandler<T> типы делегатов,и, таким образом, если есть вероятность, что наш код может использовать эти сторонние методы, мы должны использовать предопределенные делегаты EventHandler/Eventhandler<T>?

спасибо

Ответы [ 5 ]

11 голосов
/ 29 июня 2010

Для меня вопрос немного странный. Какая польза от этого в противном случае (определение типов делегатов, которые точно соответствуют EventHandler<TEventArgs> для некоторых TEventArgs)?

Тем не менее, есть, по крайней мере, одно преимущество, которое я могу себе представить, чтобы сделать это "обычным" способом: некоторые API уже ожидают обработки EventHandler<TEventArgs> делегатов; например, Rx Extensions включает метод, который выглядит следующим образом:

Observable.FromEvent<TEventArgs>(
    Action<EventHandler<TEventArgs>> addHandler,
    Action<EventHandler<TEventArgs>> removeHandler
);

Если вы определили свой собственный делегат, использование таких методов, которые ожидают EventHandler<TEventArgs> делегатов, станет более сложным, чем необходимо, без дополнительной выгоды (как я вижу, в любом случае).

7 голосов
/ 29 июня 2010

Вы забыли важный:

  • Сумасшедший, который будет поддерживать ваш код когда-нибудь, узнает, где вы живете и причинит вам боль.
5 голосов
/ 29 июня 2010

Вы ответили на свой вопрос:

  • Синтаксический сахар (меньше писать) для поддержания соглашения
  • Совместимость (использование типа EventHandler позволяет легко интегрировать события из других библиотек

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

2 голосов
/ 13 июля 2012

Я собираюсь раскачивать лодку здесь и предложить что-то совершенно еретическое.Раньше я был в лагере EventArgs, потому что я цеплялся за менталитет «MS рекомендует это, и так всегда делали», но со временем я стал ненавидеть EventArgs.Почему?

  • Это продвигает стиль кодирования .NET-1.0ish, который основан на слабой типизации / приведении типов и заставляет меня чувствовать себя нечистым.
  • Это заставляет ваш класс, который реализуетсобытие, которое загрязняет кучу новыми EventArg экземплярами каждый раз, когда она срабатывает, что также делает меня неловким.Почему бы не сделать так, чтобы мои события давали подписчикам именно то, что им нужно, вместо того, чтобы помещать их в дополнительный класс, который ничего не делает для меня.
  • Подписи ваших методов обратного вызова, которые подписываются на событие, выглядят как мусор и имеют очень малосемантическая деталь - например, object sender - ЧТО является отправителем?!?!

Теперь я объявляю своих собственных делегатов обработчиков событий, которые я аккуратно храню в своих собственных "Папка "Делегаты" в моем решении, а также их собственное пространство имен.Поэтому мой делегат может находиться в своем собственном файле, например так:

namespace MyAPI.Data.Delegates
{
    public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data);
}

Объявление события теперь выглядит следующим образом:

public event DataEventHandler<TData> DataReady = delegate { };

Преимущества этого подхода:

  • Сигнатуры метода имеют более семантическую детализацию.Вы знаете, ВОЗ отправляет ЧТО .
  • Сохраняется строгая типизация.Больше не нужно приводить object sender к тому, что, как вы думаете, должно быть.
  • Вам не нужно new() поднимать объекты и загрязнять кучу, что может быть проблематично, если ваше событие часто срабатывает.Просто передайте своим подписчикам именно то, что им нужно, будь то ссылка на объект или тип значения.
  • Используя соглашение об именовании ___EventHandler для своих делегатов, вы все равно продвигаете унифицированный стиль для своего кода, который делаетпользователям вашего API легко узнать, каковы ваши намерения.

Единственный "недостаток" заключается в том, что пользователям вашего кода трудно связать ваше событие с существующими методами, которые имеютobject sender, EventArgs e подпись.Однако этот момент спорный, потому что если ваше событие доставляет какие-либо дополнительные данные (например, вы создали собственный подкласс EventArgs), тогда им все равно придется изменить сигнатуру метода (или привести к вашему типу подкласса).В любом случае, это все еще противно.

Вот почему мне нравится мой путь.

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

Из Pro C # 2008 и платформы .NET 3.5 :

Когда компилятор обрабатывает ключевое слово event , вы автоматически получаете регистрацию иметоды отмены регистрации *, а также любые необходимые переменные-члены ** для ваших типов делегатов.... Чтобы быть уверенным, ключевое слово event - это немного больше, чем синтаксический сахар в том смысле, что оно просто экономит ваше время на печать.

* Это включает в себя перегрузку удобной +=и -= операторы.

** ... которые уже помечены private, поэтому они не могут завершиться.

Когда вы используете универсальный делегат EventHandler, вы не 'даже не нужно выписывать свой собственный тип делегата.

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