Maneira preferida de declarar eventos


14

Estou bastante satisfeito com minha compreensão do modelo de evento .NET. Acho que estou entendendo mal uma pequena nuance do sistema.

Quando comecei a colocar eventos em minhas aulas, usaria o modo padrão da seguinte maneira:

public event EventHandler<MyEventArgs> MyEvent;

Isso significava que qualquer coisa que assinasse o evento precisaria de um método como:

void HandleThatEvent(object sender, MyEventArgs args){...}

O que é legal, mas descobri que raramente me importaria com o remetente, por isso muitas assinaturas de método estavam inchadas.

Então mudei para declarar meus próprios tipos de delegados

public delegate void MyEventHandler(SomeClass argument);

O que reduziu a desordem, mas me deixou com um pequeno problema quando se tratava de manipuladores de escrita:

eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)

Então eu teria que voltar para a declaração do delegado e olhar e depois voltar e escrevê-los, ou compilá-lo e esperar para ser informado.

Então agora, em vez disso, estou apenas usando Action, Action<T>ou o modelo que se encaixa.

public event Action<SomeClass> MyEvent;

Para que eu possa passar o mouse sobre o evento e saber quais parâmetros ele espera.

Minha pergunta, depois de tudo isso: Existe uma prática recomendada para declarar eventos em c #? Devo voltar ao EventHandler<T>caminho ou é Action<T>aceitável?


Não se esqueça de certificar-se de que o manipulador seja copiado localmente para onde você dispara o evento, sempre faça isso para segurança do encadeamento.
Snoop

Você pode escrever seus próprios eventos inteligentes, médios e enxutos com segurança de tipo no código encapsulado, mas qualquer coisa que publicar deve seguir o padrão padrão ou apenas confundirá os usuários da sua classe (e aparentemente também algumas ferramentas).
Martin Maat

Respostas:


8

Para manipulação simples de eventos internos, existem aqueles que simplesmente usam Actionou Action<T>, como você está propondo. Eu costumo usar o padrão padrão, incluindo o Remetente, mesmo para eventos internos, porque você nunca sabe quando mais tarde poderá expor uma classe ou evento, e eu não gostaria da pena de ter que refatorar o método de evento apenas para fazer público.

Concordo com você que a assinatura de manipulação de eventos é um pouco mais pesada do que deveria para cenários simples, mas foi bem projetada para lidar com a migração incremental, pois argumentos de eventos adicionais podem se tornar necessários ao longo do tempo. No geral, eu continuaria com o padrão padrão, especialmente porque, como você observou, você só recebe suporte adequado do IntelliSense se o fizer.

Quanto vale a pena, dediquei algum tempo a isso e criei um padrão de manipulação de eventos diferente: Assinatura de Evento no .NET - Usando um 'Remetente' de Tipo Forte? . O objetivo aqui não era remover o remetente, mas torná-lo genericamente forte digitado como em TSendervez de fracamente digitado como System.Object. Funciona muito bem; no entanto, perde-se o suporte ao IntelliSense quando você faz isso; portanto, há uma troca infeliz.

No geral, eu continuaria com o padrão padrão, mas é interessante pensar em maneiras potencialmente melhores de fazer isso.


Obrigado por me indicar sua pergunta SO. É muito interessante. Ainda não entendo por que é tão importante que o remetente seja obrigatório. Na maioria das vezes, eu não ligo para o remetente. É apenas alguma regra arbitrária da MS?
Matt Ellen

Não, é claro que você pode declarar seus delegados como quiser. É política do .NET sempre incluir o remetente e não é uma má idéia.
1111 Neil

@ Neil: Eu entendo que ele é útil às vezes, mas não tenho a política de sempre fazê-lo - especialmente porque a MS recomenda que os eventos sejam do seu jeito. Uma das coisas de que realmente gosto nos eventos é a capacidade de dissociar as aulas. Se eu estiver incluindo o objeto, ele será acoplado novamente. Se é apenas uma questão de conformidade com o CLS, posso conviver com isso.
Matt Ellen

É acoplado novamente apenas se você usar o objeto remetente, caso contrário, não importa o que é colocado como valor do remetente, pois você não o usa. A dependência existe apenas se você precisar que exista uma dependência. Vejo de onde você vem, e se o remetente do objeto desaparecesse de todo o código de qualquer servidor do planeta, eu não ficaria acordado noites.
315 Neil

Sim, você pode enviar 'null' como remetente, se realmente quiser ... Mas, incluindo o remetente, o manipulador de eventos poderá cancelar a inscrição, se assim o desejar. No geral, porém, eu diria que conhecer a fonte do evento geralmente é muito importante.
Mike Rosenblum
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.