CA1003: Utilizar instancias genéricas de controlador de eventos
Propiedad | Value |
---|---|
Identificador de la regla | CA1003 |
Título | Utilizar instancias genéricas de controlador de eventos |
Categoría | Diseño |
La corrección es problemática o no problemática | Problemático |
Habilitado de forma predeterminada en .NET 8 | No |
Causa
Un tipo contiene un delegado que devuelve void y cuya firma contiene dos parámetros (el primero un objeto y el segundo un tipo asignable a EventArgs), y el ensamblado que lo contiene está dirigido a .NET.
De forma predeterminada, esta regla solo examina los tipos visibles externamente, pero es configurable.
Descripción de la regla
Antes de .NET Framework 2.0, para pasar información personalizada al controlador de eventos, se tenía que declarar un nuevo delegado que especificaba una clase derivada de la clase System.EventArgs. En .NET Framework 2.0 y versiones posteriores, el delegado genérico System.EventHandler<TEventArgs> permite que cualquier clase derivada de EventArgs se use junto con el controlador de eventos.
Cómo corregir infracciones
Para corregir una infracción de esta regla, quite el delegado y reemplace su uso con el delegado System.EventHandler<TEventArgs>.
Si el delegado se genera automáticamente mediante el compilador Visual Basic, cambie la sintaxis de la declaración del evento para usar el delegado System.EventHandler<TEventArgs>.
Cuándo suprimir las advertencias
No suprima las advertencias de esta regla.
Configuración del código para analizar
Use la opción siguiente para configurar en qué partes del código base ejecutar esta regla.
Puede configurar esta opción solo para esta regla, para todas las reglas a las que se aplica o para todas las reglas de esta categoría (Diseño) a las que se aplica. Para más información, vea Opciones de configuración de reglas de calidad de código.
Incluir superficies de API específicas
Puede configurar en qué partes del código base ejecutar esta regla, en función de su accesibilidad. Por ejemplo, para especificar que la regla solo se debe ejecutar en la superficie de API no públicas, agregue el siguiente par clave-valor a un archivo .editorconfig en el proyecto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Ejemplo
En el ejemplo siguiente se muestra un tipo que infringe la regla. En el ejemplo de Visual Basic, los comentarios describen cómo modificar el ejemplo para cumplir la regla. En el ejemplo de C#, se ofrece un ejemplo que muestra el 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 Main1003()
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();
}
}
En el fragmento de código siguiente se quita la declaración de delegado del ejemplo anterior, que cumple la regla. Se reemplaza su uso en los métodos ClassThatRaisesEvent
y ClassThatHandlesEvent
mediante el delegado 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();
}
}
Reglas relacionadas
- CA1005: Evitar los parámetros excesivos en tipos genéricos
- CA1010: Las colecciones deben implementar la interfaz genérica
- CA1000: No declarar miembros estáticos en tipos genéricos
- CA1002: No exponer listas genéricas