Каковы преимущества наличия событий, соответствующих правилам сети? - PullRequest
7 голосов
/ 17 февраля 2010

Я понимаю, как использовать События в соответствии с рекомендациями Net Framework, но каковы преимущества использования этого шаблона?

http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx:

В рекомендациях .NET Framework указано, что используется тип делегата. для события должно принимать два параметра, параметр «источник объекта» с указанием источника события и параметра «е», который инкапсулирует любую дополнительную информацию о событии. Тип параметр "e" должен быть производным от класса EventArgs. Для событий которые не используют никакой дополнительной информации, .NET Framework имеет уже определен соответствующий тип делегата: EventHandler.

a) Я вижу некоторые преимущества в использовании значения «источник объекта» в качестве первого параметра, поскольку в некоторых случаях события могут иметь один и тот же метод. Таким образом, если, например, у нас есть 10 объектов и если все 10 объектов устанавливают свои события в обработчик событий M, то внутри M мы можем использовать значение параметра «отправитель объекта» для идентификации инициатора вызова события.

  • Но, насколько я могу судить, параметр «источник объекта» полезен, только если событие было вызвано внутри метода экземпляра. Таким образом, если событие было вызвано внутри статического метода, то параметр «источник объекта» бесполезен ?!

b) Есть ли другие преимущества использования событий в соответствии с рекомендациями Net Framework?

в) Какими бы ни были выгоды, почему они перевешивают проблему необходимости

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

спасибо

Ответы [ 5 ]

10 голосов
/ 17 февраля 2010

Насколько я понимаю, есть два основных преимущества:

  • Люди, пишущие код, использующий событие, распознают шаблон и сразу узнают, как использовать событие
  • Подписьсобытия составлены таким образом, что оно устойчиво к изменениям

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

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

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

Я не уверен, что вы имеете в виду, имея в виду «возможность расширять EventArgs без изменения подписи события»?!

Давайтевозьмем пример, возьмем следующий класс:

public class SomeClass
{
    public event EventHandler<FileEventArgs> SomethingHappened;
}
public class FileEventArgs : EventArgs
{
    public FileEventArgs(string filename)
    {
        Filename = filename;
    }
    public string Filename { get; private set; }
}

Затем у нас есть получатель, который прослушивает событие SomethingHappened:

static void SomethingHappenedHandler(object sender, FileEventArgs e)
{
    // do something intelligent
}

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

public enum WhatHappened
{
    Copy,
    Rename,
    Delete
}
public class FileEventArgs : EventArgs
{
    public FileEventArgs(string filename, WhatHappened whatHappened)
    {
        Filename = filename;
        WhatHappened = whatHappened;
    }
    public string Filename { get; private set; }
    public WhatHappened WhatHappened { get; private set; }
}

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

Я пишу в предположении, что если событие вызывается внутри статического метода, то параметр «источник объекта» бесполезен?!

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

8 голосов
/ 17 февраля 2010

Если вы придерживаетесь руководящих принципов .NET Framework не только для событий, но и для всего, кто-то, кому нужно прочитать ваш код или использовать вашу библиотеку, распознает его, что упростит ему задачу. Это всегда хорошо, так как вы должны писать код для своих читателей, а не для вашего удобства. Хорошая вещь в .NET состоит в том, что существует стандартное руководство с самого начала, в отличие от тысяч соглашений для C ++ и т. П., И большинство людей знают это и применяют их.

Дополнительным преимуществом стандартной сигнатуры обработчика событий является то, что вы можете назначать менее специализированные обработчики событий (например, EventHandler) событию более специализированного типа, упрощая разработку, если кому-то не нужны дополнительные данные. Это также упрощает добавление обработчиков событий с помощью Reflection, что может быть полезно в определенных обстоятельствах (например, браузер иерархии объектов для некоторой объектной модели) - я могу заверить вас, что код для обработки любого события с помощью Reflection сложная вещь, которую я решил, испуская код IL для каждого события, которое я всегда рассматривал как последнее средство.

Как писал в то же время Фредрик Мёрк, это также облегчает расширение вашего события позже, добавляя параметры только в ваш производный от EventArgs класс, а не в каждый обработчик событий.

4 голосов
/ 17 февраля 2010

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

3 голосов
/ 17 февраля 2010

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

почему?

  • потому что мне не всегда нужно знать отправителя события
  • потому что перемещение аргументов делегата - особенно когда есть только один - в отдельный класс - излишне

Да, я знаю, аргументы могут измениться в будущем. Но ЯГНИ. И, честно говоря, когда мне нужно изменить аргументы в делегате события, компилятор удобно сообщает мне о каждом месте, где он использовался, чтобы я мог проверить, правильно ли они обрабатывают новые параметры. Если бы я следовал стандарту и использовал собственный класс EventArgs, мне пришлось бы искать эти места вручную.

так что, как обычно, «это зависит» и «используйте свое собственное суждение» применяются: -)

2 голосов
/ 17 февраля 2010

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

public event EventHandler<MyCustomEventArgs> MyEvent;

http://msdn.microsoft.com/en-us/library/db0etb8x.aspx

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