2023-06-14 17:17:39 +02:00

97 lines
2.6 KiB
Plaintext

== Why is this an issue?
https://learn.microsoft.com/en-us/dotnet/csharp/event-pattern#define-and-raise-field-like-events[Field-like] events are events that do not have explicit https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/add[`add`] and https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/remove[`remove`] accessors.
[source,csharp]
----
public event EventHandler MyEvent; // No add and remove accessors
----
The compiler generates a `private` `delegate` field to back the event, as well as generating the implicit `add` and `remove` accessors.
When a `virtual` field-like `event` is overridden by another field-like `event`, the behavior of the C# compiler is to generate a new `private` `delegate` field in the derived class, separate from the parent's field. This results in multiple and separate events being created, which is rarely what's actually intended.
=== Noncompliant code example
[source,csharp,diff-id=1,diff-type=noncompliant]
----
abstract class Car
{
public virtual event EventHandler OnRefuel; // Noncompliant
public void Refuel()
{
// This OnRefuel will always be null
if (OnRefuel != null)
{
OnRefuel(this, EventArgs.Empty);
}
}
}
class R2 : Car
{
public override event EventHandler OnRefuel;
}
class Program
{
static void Main(string[] args)
{
var r2 = new R2();
r2.OnRefuel += (o, a) =>
{
Console.WriteLine("This event will be called");
};
r2.Refuel();
}
}
----
=== Compliant solution
To prevent this, remove the `virtual` designation from the parent class event.
[source,csharp,diff-id=1,diff-type=compliant]
----
abstract class Car
{
public event EventHandler OnRefuel; // Compliant
public void Refuel()
{
if (OnRefuel != null)
{
OnRefuel(this, EventArgs.Empty);
}
}
}
class R2 : Car
{
}
class Program
{
static void Main(string[] args)
{
var r2 = new R2();
r2.OnRefuel += (o, a) =>
{
Console.WriteLine("This event will be called");
};
r2.Refuel();
}
}
----
== Resources
=== Documentation
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/add[Add keyword]
* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/remove[Remove keyword]
* https://learn.microsoft.com/en-us/dotnet/csharp/delegate-class[Delegates]
* https://learn.microsoft.com/en-us/dotnet/csharp/events-overview[Introduction to events]
* https://learn.microsoft.com/en-us/dotnet/csharp/event-pattern#define-and-raise-field-like-events[Field-like events]
include::../rspecator.adoc[]