Почему * мы * должны использовать EventHandler - PullRequest
33 голосов
/ 07 октября 2010

Я ненавижу EventHandler.Ненавижу, что мне приходится разыгрывать sender, если я хочу что-то с этим сделать.Ненавижу, что мне нужно создать новый класс, наследующий от EventArgs, чтобы использовать EventHandler<T>.

Мне всегда говорили, что EventHandler - это традиция, и все, что угодно.Но я не могу найти причину, по которой эта догма все еще существует.

Есть ли причина, по которой было бы плохой идеей создать нового делегата:

delegate void EventHandler<TSender, T>(TSender sender, T args);

Таким образом,sender будет безопасным для типов, и я могу передать в качестве аргументов все, что захочу (в том числе пользовательские EventArgs, если я так захочу).

Ответы [ 6 ]

24 голосов
/ 07 октября 2010

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

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

Например, если вы объявите обработчик как тип int -> void, тогда сторонний код может поставить в очередь YourEvent += Enviroment.Exit(-1) и заставить вас непреднамеренно выйти из процесса,Это, очевидно, вызовет легко обнаруживаемую проблему, но существует гораздо больше вредоносных API, которые могут быть поставлены в очередь для выполнения других задач.

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

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

9 голосов
/ 07 октября 2010

Нет причин использовать его, кроме , принятого соглашения .net , и любой, кто читает ваш код, должен понять это довольно легко.Для этого есть веская причина.

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

6 голосов
/ 07 октября 2010

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

2 голосов
/ 07 октября 2010

Я согласен с вами, соглашение глупо и / или устарело.Делайте это правильно, с надлежащей безопасностью типов и дженериков.

Все время возникает задача, которую вы должны выполнить, и вы можете следовать тому, как это делал последний парень, ИЛИ делать это другим способом, который, по вашему мнению, лучше.обычно выбирают первый выбор - делайте это так же, как последний парень, и у вас не будет проблем.Но второй выбор - это то, что улучшает программное обеспечение в течение длительного времени.(Или, по крайней мере, это МОЖЕТ улучшить его, если вы правы, что ваш путь лучше! :))

2 голосов
/ 07 октября 2010

Что ж, при выполнении всего этого приведения необычно, клиентский код довольно часто уже знает, кто такой отправитель , потому что он явно подписал событие только на один объект.Совместное использование обработчиков событий довольно редко.Если общее поведение является желательным, то лучший подход состоит в том, чтобы извлечь из класса и переопределить метод OnXxxx.После этого вы больше не заботитесь о sender , вы получили this .

Но, решите свою проблему тривиально, включив безопасную ссылку на отправителя в свои пользовательские EventArgsпроизводный класс.

0 голосов
/ 07 октября 2010

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

Использование делегата EventHandler представляет собой руководствоздесь: http://msdn.microsoft.com/en-us/library/ms229011.aspx

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