Não vejo vantagens em usar eventos sobre delegados, além de ser um açúcar sintático. Talvez eu esteja entendendo mal, mas parece que o evento é apenas um espaço reservado para delegado.
Você poderia me explicar as diferenças e quando usá-las? Quais são as vantagens e desvantagens? Nosso código está fortemente enraizado em eventos e quero chegar ao fundo disso.
Quando você usaria delegados em eventos e vice-versa? Informe sua experiência no mundo real com ambos, digamos, no código de produção.
Respostas:
Do ponto de vista técnico, outras respostas abordaram as diferenças.
De uma perspectiva semântica, os eventos são ações geradas por um objeto quando certas condições são atendidas. Por exemplo, minha classe Stock tem uma propriedade chamada Limit e gera um evento quando o preço das ações atinge o Limit. Esta notificação é feita por meio de um evento. Se alguém realmente se preocupa com este evento e se inscreve nele está além da preocupação da classe do proprietário.
Um delegado é um termo mais genérico para descrever uma construção semelhante a um ponteiro em termos C / C ++. Todos os delegados em .Net são delegados multicast. De uma perspectiva semântica, eles geralmente são usados como um tipo de entrada. Em particular, eles são uma maneira perfeita de implementar o Padrão de Estratégia . Por exemplo, se eu quiser classificar uma Lista de objetos, posso fornecer uma estratégia de Comparador para o método para dizer à implementação como comparar dois objetos.
Usei os dois métodos no código de produção. Toneladas de meus objetos de dados notificam quando certas propriedades são atendidas. Exemplo mais básico, sempre que uma propriedade é alterada, um evento PropertyChanged é gerado (consulte a interface INotifyPropertyChanged). Usei delegados no código para fornecer diferentes estratégias de transformar certos objetos em strings. Este exemplo específico foi uma lista ToString () glorificada de implementações para um tipo de objeto específico para exibi-lo aos usuários.
fonte
A palavra
event
- chave é um modificador de escopo para delegados multicast. As diferenças práticas entre isso e apenas declarar um delegado multicast são as seguintes:event
em uma interface.public event
).Por uma questão de interesse, você pode aplicar
+
e-
a delegados multicast, e esta é a base da sintaxe+=
e-=
para a atribuição de combinação de delegados a eventos. Esses três snippets são equivalentes:Amostra dois, ilustrando a atribuição direta e a atribuição combinada.
Amostra três: sintaxe mais familiar. Você provavelmente está familiarizado com a atribuição de null para remover todos os manipuladores.
Assim como as propriedades, os eventos têm uma sintaxe completa que ninguém usa. Este:
... faz exatamente o mesmo:
Os métodos add e remove são mais evidentes na sintaxe bastante afetada que o VB.NET usa (sem sobrecargas de operador).
fonte
Os eventos são açúcares sintáticos. Eles são deliciosos. Quando vejo um evento, sei o que fazer. Quando vejo um delegado, não tenho tanta certeza.
Combinar eventos com interfaces (mais açúcar) é um lanche de dar água na boca. Delegados e classes abstratas virtuais puras são muito menos atraentes.
fonte
Os eventos são marcados como tal nos metadados. Isso permite que coisas como Windows Forms ou ASP.NET designers diferenciem eventos de meras propriedades do tipo delegado e forneçam suporte apropriado para eles (especificamente mostrando-os na guia Eventos da janela Propriedades).
Outra diferença de uma propriedade do tipo delegado é que os usuários podem apenas adicionar e remover manipuladores de eventos, enquanto com uma propriedade do tipo delegado eles podem definir o valor:
Isso ajuda a isolar os assinantes do evento: posso adicionar meu manipulador a um evento e você pode adicionar seu manipulador ao mesmo evento, e você não substituirá acidentalmente meu manipulador.
fonte
Embora os eventos sejam normalmente implementados com delegados multicast, não há requisitos para que sejam usados dessa maneira. Se uma classe expõe um evento, isso significa que a classe expõe dois métodos. Seus significados são, em essência:
A maneira mais comum de uma classe manipular um evento que expõe é definir um delegado multicast e adicionar / remover qualquer delegado que seja passado para os métodos acima, mas não há nenhum requisito de que funcionem dessa forma. Infelizmente, a arquitetura do evento falha em fazer algumas coisas que teriam tornado as abordagens alternativas muito mais limpas (por exemplo, fazer com que o método de inscrição retornasse um MethodInvoker, que seria mantido pelo assinante; para cancelar a inscrição de um evento, simplesmente invoque o método retornado), portanto, delegados multicast são de longe a abordagem mais comum.
fonte
para entender as diferenças, você pode olhar para estes 2 exemplos
Exemplo com delegados (ação neste caso que é um tipo de delegado que não retorna valor)
para usar o delegado, você deve fazer algo assim
este código funciona bem, mas você pode ter alguns pontos fracos.
Por exemplo, se eu escrever isso
com a última linha de código que substituí os comportamentos anteriores, apenas faltando um
+
(usei em+
vez de+=
)Outro ponto fraco é que cada classe que usa sua
Animal
classe pode aumentarRaiseEvent
apenas pagandoanimal.RaiseEvent()
.Para evitar esses pontos fracos, você pode usar
events
em c #.Sua classe Animal mudará desta forma
chamar eventos
Diferenças:
notas
EventHandler é declarado como o seguinte delegado:
leva um remetente (do tipo Object) e argumentos de evento. O remetente é nulo se vier de métodos estáticos.
Você também pode usar
EventHAndler
este exemplo que usaEventHandler<ArgsSpecial>
consulte aqui a documentação sobre o EventHandler
fonte
Quando projeto minhas próprias APIs, defino delegados que são passados como parâmetros para métodos ou para os construtores de classes:
Predicate
eAction
são passados para as classes de coleção genérica .Net)Esses delegados geralmente não são opcionais em tempo de execução (ou seja, não devem ser
null
).Eu tendo a não usar eventos; mas onde eu uso eventos, eu os uso opcionalmente para sinalizar eventos para zero, um ou mais clientes que possam estar interessados, ou seja, quando faz sentido que uma classe (por exemplo, o
System.Windows.Form
classe) deva existir e ser executada, quer qualquer cliente tenha ou não adicionou um manipulador de eventos ao seu evento (por exemplo, o evento 'mouse down' do formulário existe, mas é opcional se algum cliente externo está interessado em instalar um manipulador de eventos naquele evento).fonte
Embora eu não tenha motivos técnicos para isso, eu uso eventos no código de estilo da IU, em outras palavras, nos níveis mais altos do código, e uso delegados para lógica que se estende mais profundamente no código. Como eu disse, você poderia usar qualquer um dos dois, mas acho que esse padrão de uso é lógico, pelo menos ajuda a documentar os tipos de retorno de chamada e sua hierarquia também.
Edit: Acho que a diferença nos padrões de uso que tenho seria que, acho perfeitamente aceitável ignorar eventos, eles são ganchos / stubs, se você precisa saber sobre o evento, ouça-os, se você não se preocupa com o evento apenas ignore. É por isso que eu os uso para UI, tipo de estilo de evento Javascript / Browser. No entanto, quando eu tenho um delegado, espero REALMENTE esperar que alguém cuide da tarefa do delegado e lance uma exceção se não for tratada.
fonte
A diferença entre eventos e delegados é muito menor do que eu pensava. Acabei de postar um vídeo super curto no YouTube sobre o assunto: https://www.youtube.com/watch?v=el-kKK-7SBU
Espero que isto ajude!
fonte
fonte