CA1003: Generische Ereignishandlerinstanzen verwenden.
Eigenschaft | Wert |
---|---|
Regel-ID | CA1003 |
Titel | Generische Ereignishandlerinstanzen verwenden. |
Kategorie | Design |
Fix führt oder führt nicht zur Unterbrechung | Breaking |
Standardmäßig in .NET 8 aktiviert | Nein |
Ursache
Ein Typ enthält einen Delegaten, der leer zurückgegeben wird und dessen zugehörige Signatur zwei Parameter enthält (der erste ist ein Objekt, der zweite ein Typ, der EventArgs zugewiesen werden kann). Das Ziel der enthaltenen Assembly ist .NET.
Standardmäßig werden mit dieser Regel nur extern sichtbare Typen überprüft, aber dies ist konfigurierbar.
Regelbeschreibung
Vor .NET Framework 2.0 musste zur Weitergabe einer benutzerdefinierten Information an den Ereignishandler ein neuer Delegat deklariert werden, mit dem eine von der System.EventArgs-Klasse abgeleitete Klasse spezifiziert wurde. In .NET Framework 2.0 und späteren Versionen gibt es einen generischen System.EventHandler<TEventArgs>-Delegaten. Durch diesen kann jede von EventArgs abgeleitete Klasse gemeinsam mit dem Ereignishandler genutzt werden.
Behandeln von Verstößen
Um einen Verstoß gegen diese Regel zu beheben, entfernen Sie den Delegaten, und ersetzen Sie ihn mit dem System.EventHandler<TEventArgs>-Delegaten.
Wenn der Delegat automatisch vom Visual Basic-Compiler generiert wird, müssen Sie die Syntax der Ereignisdeklaration ändern, um den System.EventHandler<TEventArgs>-Delegaten verwenden zu können.
Wann sollten Warnungen unterdrückt werden?
Unterdrücken Sie keine Warnung dieser Regel.
Konfigurieren des zu analysierenden Codes
Mithilfe der folgenden Option können Sie konfigurieren, für welche Teile Ihrer Codebasis diese Regel ausgeführt werden soll.
Sie können diese Optionen nur für diese Regel, für alle zutreffenden Regeln oder für alle zutreffenden Regeln in dieser Kategorie (Entwurf) konfigurieren. Weitere Informationen finden Sie unter Konfigurationsoptionen für die Codequalitätsregel.
Einschließen bestimmter API-Oberflächen
Sie können je nach Zugänglichkeit festlegen, für welche Bestandteile Ihrer Codebasis diese Regel ausgeführt wird. Sie können beispielsweise festlegen, dass die Regel nur für die nicht öffentliche API-Oberfläche ausgeführt werden soll, indem Sie einer EDITORCONFIG-Datei in Ihrem Projekt das folgende Schlüssel-Wert-Paar hinzufügen:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Beispiel
Das folgende Beispiel zeigt einen Delegaten, der gegen die Regel verstößt. Im Visual Basic-Beispiel wird durch Kommentare beschrieben, wie das Beispiel modifiziert werden kann, um die Regel zu erfüllen. Nach dem C#-Beispiel folgt ein weiteres Beispiel mit dem geänderten Code.
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();
}
}
Mit dem folgenden Codeausschnitt wird die Deklaration des Delegaten aus dem vorherigen Beispiel entfernt, wodurch die Regel erfüllt wird. Er ersetzt sie bei den ClassThatRaisesEvent
- und ClassThatHandlesEvent
-Methoden mit dem System.EventHandler<TEventArgs>-Delegaten.
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();
}
}
Ähnliche Regeln
- CA1005: Übermäßige Anzahl von Parametern in generischen Typen vermeiden.
- CA1010: Sammlungen müssen eine generische Schnittstelle implementieren.
- CA1000: Statische Member nicht in generischen Typen deklarieren.
- CA1002: Generische Listen nicht verfügbar machen.