CA1003 : Utiliser les instances du gestionnaire d'événements génériques
Propriété | Value |
---|---|
Identificateur de la règle | CA1003 |
Titre | Utiliser les instances du gestionnaire d'événements génériques |
Catégorie | Conception |
Le correctif est cassant ou non cassant | Rupture |
Activée par défaut dans .NET 9 | Non |
Cause
Un type contient un délégué qui retourne void, dont la signature contient deux paramètres (le premier est un objet et le second est un type pouvant être assigné à EventArgs), et l’assembly conteneur cible .NET.
Par défaut, cette règle examine uniquement les types visibles en externe, mais elle est configurable.
Description de la règle
Avant .NET Framework 2.0, afin de transmettre des informations personnalisées au gestionnaire d’événements, un nouveau délégué devait être déclaré qui spécifiait une classe dérivée de la classe System.EventArgs. Dans .NET Framework 2.0 et versions ultérieures, le délégué générique System.EventHandler<TEventArgs> permet à toute classe dérivée de EventArgs d’être utilisée avec le gestionnaire d’événements.
Comment corriger les violations
Pour corriger une infraction de cette règle, supprimez le délégué et remplacez son utilisation à l’aide du délégué System.EventHandler<TEventArgs>.
Si le délégué est généré automatiquement par le compilateur Visual Basic, modifiez la syntaxe de la déclaration d’événement pour utiliser le délégué System.EventHandler<TEventArgs>.
Quand supprimer les avertissements
Ne supprimez aucun avertissement de cette règle.
Configurer le code à analyser
Utilisez l’option suivante pour configurer les parties de votre codebase sur lesquelles exécuter cette règle.
Vous pouvez configurer cette option pour cette règle uniquement, pour toutes les règles auxquelles elle s’applique ou pour toutes les règles de cette catégorie (Conception) auxquelles elle s’applique. Pour plus d’informations, consultez Options de configuration des règles de qualité du code.
Inclure des surfaces d’API spécifiques
Vous pouvez configurer les parties de votre codebase sur lesquelles exécuter cette règle, en fonction de leur accessibilité. Par exemple, pour spécifier que la règle doit s’exécuter uniquement sur la surface d’API non publique, ajoutez la paire clé-valeur suivante à un fichier .editorconfig dans votre projet :
dotnet_code_quality.CAXXXX.api_surface = private, internal
Exemple
L’exemple suivant montre un délégué qui enfreint la règle. Dans l’exemple Visual Basic, les commentaires décrivent comment modifier l’exemple pour satisfaire la règle. Pour l’exemple C#, un exemple suivant montre le code modifié.
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();
}
}
L’extrait de code suivant supprime la déclaration de délégué de l’exemple précédent, qui satisfait à la règle. Il remplace son utilisation dans les méthodes ClassThatRaisesEvent
et ClassThatHandlesEvent
en utilisant le délégué 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();
}
}
Règles associées
- CA1005 : Éviter les paramètres excessifs sur les types génériques
- CA1010 : Les collections doivent implémenter une interface générique
- CA1000 : Ne pas déclarer de membres statiques sur les types génériques
- CA1002 : N’exposez pas de listes génériques