É possível cancelar a inscrição de um método anônimo de um evento?
Se eu me inscrever em um evento como este:
void MyMethod()
{
Console.WriteLine("I did it!");
}
MyEvent += MyMethod;
Posso cancelar a assinatura assim:
MyEvent -= MyMethod;
Mas se eu me inscrever usando um método anônimo:
MyEvent += delegate(){Console.WriteLine("I did it!");};
é possível cancelar a inscrição desse método anônimo? Se sim, como?
Respostas:
Basta manter uma referência ao delegado.
fonte
Uma técnica é declarar uma variável para armazenar o método anônimo, que estaria disponível no próprio método anônimo. Isso funcionou para mim porque o comportamento desejado era cancelar a inscrição após o tratamento do evento.
Exemplo:
fonte
De memória, a especificação explicitamente não garante o comportamento de qualquer maneira quando se trata da equivalência de delegados criados com métodos anônimos.
Se precisar cancelar a inscrição, você deve usar um método "normal" ou reter o delegado em outro lugar para poder cancelar a inscrição exatamente com o mesmo delegado usado para assinar.
fonte
Na versão 3.0 pode ser reduzido para:
fonte
Como o recurso de funções locais do C # 7.0 foi lançado, a abordagem sugerida por J c se torna realmente interessante.
Portanto, honestamente, você não tem uma função anônima como variável aqui. Mas suponho que a motivação para usá-lo no seu caso possa ser aplicada a funções locais.
fonte
Em vez de manter uma referência a qualquer delegado, você pode instrumentar sua classe para devolver a lista de chamadas do evento ao chamador. Basicamente, você pode escrever algo assim (assumindo que MyEvent seja declarado dentro de MyClass):
Assim, você pode acessar toda a lista de chamadas de fora do MyClass e cancelar a inscrição de qualquer manipulador que desejar. Por exemplo:
Eu escrevi um post completo sobre esta técnica aqui .
fonte
Tipo de abordagem manca:
Isso pode não funcionar ou ser o método mais eficiente, mas deve fazer o trabalho.
fonte
Se você quiser controlar o cancelamento da inscrição, precisará seguir a rota indicada na sua resposta aceita. No entanto, se você estiver apenas preocupado em limpar as referências quando sua classe de assinante ficar fora do escopo, haverá outra solução (um pouco complicada) que envolve o uso de referências fracas. Acabei de postar uma pergunta e resposta sobre este tópico.
fonte
Uma solução simples:
basta passar a variável eventhandle como parâmetro para si mesma. Evento, se você tiver o caso de não conseguir acessar a variável criada original devido ao multithreading, poderá usar este:
fonte
MyEvent -= myEventHandlerInstance;
ser executado? Se for possível, você terá um erro. Mas não tenho certeza se é esse o caso.se você quiser se referir a algum objeto com esse delegado, pode ser que você possa usar Delegate.CreateDelegate (Type, Object target, MethodInfo methodInfo) .net considere o delegado igual a target e methodInfo
fonte
Se a melhor maneira é manter uma referência no eventHandler inscrito, isso pode ser obtido usando um Dicionário.
Neste exemplo, eu tenho que usar um método anônimo para incluir o parâmetro mergeColumn para um conjunto de DataGridViews.
O uso do método MergeColumn com o parâmetro enable definido como true habilita o evento enquanto o usa com false o desativa.
fonte