Pergunta

Tome a seguinte classe C #:

c1 {
 event EventHandler someEvent;
}

Se há um monte de assinaturas de evento c1 de someEvent e quero limpar todos eles, o que é a melhor maneira de conseguir isso? Considere também que as assinaturas a este evento poderia ser / são lambdas / delegados anônimos.

Atualmente a minha solução é adicionar um método ResetSubscriptions() para c1 que conjuntos someEvent como nulo. Eu não sei se isso tem quaisquer consequências invisíveis.

Foi útil?

Solução

De dentro da classe, você pode definir a variável (oculto) como nulo. Uma referência nula é a forma canónica de representar uma lista de invocação vazio, de forma eficaz.

De fora da classe, você não pode fazer isso -. Acontecimentos basicamente expor "assinar" e "unsubscribe" e é isso

É ser consciente de eventos que campo-like pena está realmente fazendo - eles estão criando uma variável e um evento ao mesmo tempo. Dentro da classe, você acaba fazendo referência à variável. Do lado de fora, você referenciar o evento.

Veja o artigo a minha em eventos e delegados para mais informações.

Outras dicas

Adicionar um método para c1 que irá definir 'SomeEvent' como nulo ...

class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() {someEvent = null;}
}
class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() {someEvent = delegate{};}
}

É melhor uso delegado {} de null

Definir o evento para nula dentro das obras de classe. Quando eliminar uma classe que você deve sempre definir o evento como nulo, o GC tem problemas com eventos e não podem limpar a classe eliminados se tiver pendurado eventos.

A melhor prática para limpar todos os assinantes é definir o SomeEvent como nulo adicionando outro método público, se você deseja expor essa funcionalidade para fora. Isto não tem consequências invisíveis. A pré-condição é se lembrar de declarar SomeEvent com a palavra chave 'evento'.

Por favor, veja o livro -. C # 4.0, no resumo, página 125

Alguém aqui proposto método de uso Delegate.RemoveAll. Se você usá-lo, o código de exemplo poderia seguir o formulário abaixo. Mas é realmente estúpido. Porque não basta SomeEvent=null dentro da função ClearSubscribers()?

   public void ClearSubscribers ()
    {
          SomeEvent = (EventHandler) Delegate.RemoveAll(SomeEvent, SomeEvent);// Then you will find SomeEvent is set to null.
    }

Você pode conseguir isso usando os métodos Delegate.Remove ou Delegate.RemoveAll.

conceitual comentário chato estendida.

Eu prefiro usar a palavra "manipulador de eventos" em vez de "evento" ou "delegado". E usou a palavra "evento" para outras coisas. Em algumas linguagens de programação (VB.NET, Object Pascal, Objective-C), "evento" é chamado de "mensagem" ou "sinal", e até mesmo ter uma palavra-chave "mensagem", e sintaxe de açúcar específico.

const
  WM_Paint = 998;  // <-- "question" can be done by several talkers
  WM_Clear = 546;

type
  MyWindowClass = class(Window)
    procedure NotEventHandlerMethod_1;
    procedure NotEventHandlerMethod_17;

    procedure DoPaintEventHandler; message WM_Paint; // <-- "answer" by this listener
    procedure DoClearEventHandler; message WM_Clear;
  end;

E, a fim de responder a essa "mensagem", um "manipulador de eventos" responder, se é um único delegado ou vários delegados.

Resumo: "Evento" é a "questão", "manipulador de eventos (s)" são a resposta (s).

Esta é a minha solução:

public class Foo : IDisposable
{
    private event EventHandler _statusChanged;
    public event EventHandler StatusChanged
    {
        add
        {
            _statusChanged += value;
        }
        remove
        {
            _statusChanged -= value;
        }
    }

    public void Dispose()
    {
        _statusChanged = null;
    }
}

Você precisa chamar Dispose() ou utilização using(new Foo()){/*...*/} padrão de cancelar todos os membros da lista de invocação.

Remover todos os eventos, suponha que o evento é um tipo de "Action":

Delegate[] dary = TermCheckScore.GetInvocationList();

if ( dary != null )
{
    foreach ( Delegate del in dary )
    {
        TermCheckScore -= ( Action ) del;
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top