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 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();
    }
}

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();
    }
}

Siehe auch