Pergunta

Eu tenho uma classe base DockedToolWindow :Formulário, e muitas classes que derivam de DockedToolWindow.Eu tenho uma classe de contêiner que possui e atribui eventos para DockedToolWindow objetos, no entanto, quero chamar os eventos da classe filho.

Na verdade, eu tenho uma pergunta sobre como implementar o que esta Site do MSDN está me dizendo para fazer.Esta secção abaixo está a dar-me o problema:

    // The event. Note that by using the generic EventHandler<T> event type
    // we do not need to declare a separate delegate type.
    public event EventHandler<ShapeEventArgs> ShapeChanged;

    public abstract void Draw();

    //The event-invoking method that derived classes can override.
    protected virtual void OnShapeChanged(ShapeEventArgs e)
    {
        // Make a temporary copy of the event to avoid possibility of
        // a race condition if the last subscriber unsubscribes
        // immediately after the null check and before the event is raised.
        EventHandler<ShapeEventArgs> handler = ShapeChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }

Com certeza esse exemplo compila e funciona, mas quando eu substituir "ShapeChanged" com "move" (Mover um evento que eu adquiridos a partir de derivados de Formulário), ela erros dizendo que eu não posso ter de Mover-se sobre o lado direito sem += ou=.Eu também removido o ShapeEventArgs genérico tags.

Qualquer incitar sobre por que isso não está funcionando?Qual é a diferença entre um evento declaradas dentro da classe, e que é herdada?

Foi útil?

Solução

Você não pode disparar diretamente eventos de classe base. Esta é exatamente a razão pela qual você teve que fazer o seu OnShapeChanged método protected ao invés de private.

Usar base.onmove () em vez de.

Outras dicas

Da linguagem C# spec, seção 10.7 (grifo do autor):

Dentro do texto do programa da classe ou struct que contém a declaração de um evento, alguns eventos podem ser usados como campos de.Para ser usado dessa forma, um evento não deve ser abstrata ou externo, e não deve incluir explicitamente o evento-accessor-declarações.Tal evento pode ser utilizado em qualquer contexto que permite a um campo.O campo contém um delegado (§15), o qual refere-se à lista de manipuladores de eventos que foram adicionados para o evento.Se não manipuladores de eventos foram adicionados, o campo contém um valor nulo.

Assim, a razão, não se pode tratar o evento de Mover como um campo é que ele é definido em um tipo diferente (neste caso, sua superclasse).Eu concordo com o @womp especulação do que os designers fizeram essa opção para impedir que não intencional monkeying com o evento.Parece que, obviamente, ruim para permitir que tipos independentes (tipos não derivada do tipo de declarar o evento) para fazer isso, mas até mesmo de tipos derivados, que pode não ser desejável.Eles provavelmente teriam a sintaxe de inclusão, para permitir que a declaração de evento a ser feita private ou protected com relação ao campo de estilo de uso, por isso meu palpite é que eles optaram por simplesmente não permitir que ele se realize.

A diferença é o escopo. Dentro da sua classe, você pode controlar como os delegados do evento são tratados, no entanto, sua classe não pode controlar o que a classe base está fazendo. Pode estar fazendo algumas coisas loucas nos bastidores com o evento e seus manipuladores. Se você simplesmente "transferisse" o evento de movimentação, estaria eliminando a lista de delegados multicast para o evento.

Acho que eles colocam uma restrição do compilador sobre isso porque é uma prática muito insegura e essencialmente daria a qualquer classe descendente a capacidade de destruir o modelo de evento de seus pais.

Você só precisa do código que você postou na classe em que o próprio evento é definido. Todas as classes derivadas devem simplesmente ligar diretamente para o OnshaPeChanged () ou OnMove (), sem a cópia etc., para que você não esteja escrevendo esse código em suas classes (já que o evento de movimentação é definido na base).

Se você precisar fazer algum tipo de processamento na classe derivada (talvez você precise mexer com sua aula de coleção?), Você substitui a chamada virtual do Onxxx e faz coisas antes de ligar para base.onxxx (). No artigo do MSDN, a classe Circle corresponde à sua classe DockedToolWindow. O mesmo padrão deve estar disponível para suas classes derivadas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top