CA1003: Usar instâncias do manipulador de eventos genérico

Property Valor
ID da regra CA1003
Título Usar instâncias do manipulador de eventos genérico
Categoria Projetar
Correção interruptiva ou sem interrupção Quebra
Habilitado por padrão no .NET 8 Não

Causa

Um tipo contém um representante que retorna nulo, cuja assinatura contém dois parâmetros (o primeiro é um objeto e o segundo é um tipo atribuível a EventArgs), e o destino do assembly de contenção é o .NET.

Por padrão, essa regra analisa apenas os tipos visíveis externamente, mas isso é configurável.

Descrição da regra

Antes do .NET Framework 2.0, para transmitir informações personalizadas ao manipulador de eventos, um novo representante tinha de ser declarado para especificar uma classe derivada da classe System.EventArgs. No .NET Framework 2.0 e versões posteriores, o representante genérico System.EventHandler<TEventArgs> permite que qualquer classe derivada de EventArgs seja usada com o manipulador de eventos.

Como corrigir violações

Para corrigir uma violação dessa regra, remova o representante e substitua seu uso pelo uso do representante System.EventHandler<TEventArgs>.

Se o representante for gerado automaticamente pelo compilador do Visual Basic, altere a sintaxe da declaração de evento para usar o representante System.EventHandler<TEventArgs>.

Quando suprimir avisos

Não suprima um aviso nessa regra.

Configurar código para analisar

Use a opção a seguir para configurar em quais partes da base de código essa regra deve ser executada.

Você pode configurar essa opção apenas para essa regra, para todas as regras às quais ela se aplica ou para todas as regras nessa categoria (Design) às quais ela se aplica. Para saber mais, confira Opções de configuração de regra de qualidade de código.

Incluir superfícies de API específicas

É possível configurar em quais partes da base de código essa regra deverá ser executada, com base na acessibilidade. Por exemplo, para especificar que a regra deverá ser executada apenas na superfície de API não pública, adicione o seguinte par chave-valor a um arquivo .editorconfig no projeto:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Exemplo

O exemplo a seguir mostra um representante que viola a regra. No exemplo do Visual Basic, os comentários descrevem como modificar o exemplo para atender à regra. No caso do exemplo em C#, veja a seguir um exemplo com o código modificado.

Imports System

Namespace ca1003

    Public Class CustomEventArgs
        Inherits EventArgs

        Public info As String = "data"

    End Class

    Public Class ClassThatRaisesEvent

        ' This statement creates a new delegate, which violates the rule.
        Event SomeEvent(sender As Object, e As CustomEventArgs)

        ' To satisfy the rule, comment out the previous line 
        ' and uncomment the following line.
        'Event SomeEvent As EventHandler(Of CustomEventArgs)

        Protected Overridable Sub OnSomeEvent(e As CustomEventArgs)
            RaiseEvent SomeEvent(Me, e)
        End Sub

        Sub SimulateEvent()
            OnSomeEvent(New CustomEventArgs())
        End Sub

    End Class

    Public Class ClassThatHandlesEvent

        Sub New(eventRaiser As ClassThatRaisesEvent)
            AddHandler eventRaiser.SomeEvent, AddressOf HandleEvent
        End Sub

        Private Sub HandleEvent(sender As Object, e As CustomEventArgs)
            Console.WriteLine("Event handled: {0}", e.info)
        End Sub

    End Class

    Class Test

        Shared Sub Main()

            Dim eventRaiser As New ClassThatRaisesEvent()
            Dim eventHandler As New ClassThatHandlesEvent(eventRaiser)

            eventRaiser.SimulateEvent()

        End Sub

    End Class

End Namespace
// This delegate violates the rule.
public delegate void CustomEventHandler(object sender, CustomEventArgs e);

public class CustomEventArgs : EventArgs
{
    public string info = "data";
}

public class ClassThatRaisesEvent
{
    public event CustomEventHandler? SomeEvent;

    protected virtual void OnSomeEvent(CustomEventArgs e)
    {
        SomeEvent?.Invoke(this, e);
    }

    public void SimulateEvent()
    {
        OnSomeEvent(new CustomEventArgs());
    }
}

public class ClassThatHandlesEvent
{
    public ClassThatHandlesEvent(ClassThatRaisesEvent eventRaiser)
    {
        eventRaiser.SomeEvent += new CustomEventHandler(HandleEvent);
    }

    private void HandleEvent(object sender, CustomEventArgs e)
    {
        Console.WriteLine("Event handled: {0}", e.info);
    }
}

class Test
{
    static void MainEvent()
    {
        var eventRaiser = new ClassThatRaisesEvent();
        var eventHandler = new ClassThatHandlesEvent(eventRaiser);

        eventRaiser.SimulateEvent();
    }
}

O snippet de código a seguir remove a declaração de representante do exemplo anterior, que atende à regra. Ele substitui seu uso nos métodos e ClassThatRaisesEventClassThatHandlesEvent pelo uso do representante System.EventHandler<TEventArgs>.

public class CustomEventArgs : EventArgs
{
    public string info = "data";
}

public class ClassThatRaisesEvent
{
    public event EventHandler<CustomEventArgs>? SomeEvent;

    protected virtual void OnSomeEvent(CustomEventArgs e)
    {
        SomeEvent?.Invoke(this, e);
    }

    public void SimulateEvent()
    {
        OnSomeEvent(new CustomEventArgs());
    }
}

public class ClassThatHandlesEvent
{
    public ClassThatHandlesEvent(ClassThatRaisesEvent eventRaiser)
    {
        eventRaiser.SomeEvent += new EventHandler<CustomEventArgs>(HandleEvent);
    }

    private void HandleEvent(object? sender, CustomEventArgs e)
    {
        Console.WriteLine("Event handled: {0}", e.info);
    }
}

class Test
{
    static void MainEvent()
    {
        var eventRaiser = new ClassThatRaisesEvent();
        var eventHandler = new ClassThatHandlesEvent(eventRaiser);

        eventRaiser.SimulateEvent();
    }
}

Confira também