Ca1003: Utilizzare istanze di gestori eventi generici
Proprietà | valore |
---|---|
ID regola | CA1003 |
Titolo | Usare istanze di gestori eventi generici |
Categoria | Progettazione |
Correzione che causa un'interruzione o un'interruzione | Interruzione |
Abilitato per impostazione predefinita in .NET 8 | No |
Causa
Un tipo contiene un delegato che restituisce void e la cui firma contiene due parametri (il primo oggetto e il secondo un tipo assegnabile a EventArgs) e l'assembly contenitore è destinato a .NET.
Per impostazione predefinita, questa regola esamina solo i tipi visibili esternamente, ma è configurabile.
Descrizione regola
Prima di .NET Framework 2.0, per passare informazioni personalizzate al gestore eventi, un nuovo delegato doveva essere dichiarato che specificava una classe derivata dalla System.EventArgs classe . In .NET Framework 2.0 e versioni successive, il delegato generico System.EventHandler<TEventArgs> consente l'uso di qualsiasi classe derivata da EventArgs con il gestore eventi.
Come correggere le violazioni
Per correggere una violazione di questa regola, rimuovere il delegato e sostituirlo usando il System.EventHandler<TEventArgs> delegato .
Se il delegato viene generato automaticamente dal compilatore Visual Basic, modificare la sintassi della dichiarazione di evento per usare il System.EventHandler<TEventArgs> delegato.
Quando eliminare gli avvisi
Non escludere un avviso da questa regola.
Configurare il codice da analizzare
Usare l'opzione seguente per configurare le parti della codebase in cui eseguire questa regola.
È possibile configurare questa opzione solo per questa regola, per tutte le regole a cui si applica o per tutte le regole in questa categoria (Progettazione) a cui si applica. Per altre informazioni, vedere Opzioni di configurazione delle regole di qualità del codice.
Includere superfici API specifiche
È possibile configurare le parti della codebase in modo da eseguire questa regola in base all'accessibilità. Ad esempio, per specificare che la regola deve essere eseguita solo sulla superficie dell'API non pubblica, aggiungere la coppia chiave-valore seguente a un file con estensione editorconfig nel progetto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Esempio
Nell'esempio seguente viene illustrato un delegato che viola la regola. Nell'esempio di Visual Basic i commenti descrivono come modificare l'esempio per soddisfare la regola. Per l'esempio C#, un esempio segue che mostra il codice modificato.
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();
}
}
Il frammento di codice seguente rimuove la dichiarazione del delegato dall'esempio precedente, che soddisfa la regola. Sostituisce l'uso ClassThatRaisesEvent
nei metodi e ClassThatHandlesEvent
usando il System.EventHandler<TEventArgs> delegato .
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();
}
}
Regole correlate
- CA1005: Evitare un uso eccessivo di parametri nei tipi generici
- CA1010: Le raccolte devono implementare un'interfaccia generica
- CA1000: Non dichiarare membri statici su tipi generici
- CA1002: Non esporre elenchi generici