Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guidelines for events since non-nullable references

Tags:

c#

When working with C# 8 and the new non-nullable references, I realized that events are treated like fields. This means that they will cause a warning 90% of the time since they won't be initialized until someone subscribes to it.

Consider the following event:

public event EventHandler IdleTimeoutReached; 

You get the following warning on the line of the constructor declaration.

CS8618 C# Non-nullable event is uninitialized. Consider declaring the event as nullable.

If you make it nullable, the warning disappears of course. However, this looks very weird to me.

public event EventHandler? IdleTimeoutReached; 

An alternative would be assigning it a no-op, but this seems even worse.

public event EventHandler IdleTimeoutReached = new EventHandler((o, e) => { }); 

What's the correct way to handle this situation and get rid of the warning without just disabling it? Are there any official guidelines for this?

like image 582
Joelius Avatar asked Oct 14 '19 12:10

Joelius


People also ask

What is a non nullable reference type?

A reference isn't supposed to be null.The default state of a nonnullable reference variable is not-null. The compiler enforces rules that ensure it's safe to dereference these variables without first checking that it isn't null: The variable must be initialized to a non-null value.

Should I use nullable reference types?

Although using nullable reference types can introduce its own set of problems, I still think it's beneficial because it helps you find potential bugs and allows you to better express your intent in the code. For new projects, I would recommend you enable the feature and do your best to write code without warnings.

What is non nullable?

Nullable variables may either contain a valid value or they may not — in the latter case they are considered to be nil . Non-nullable variables must always contain a value and cannot be nil . In Oxygene (as in C# and Java), the default nullability of a variable is determined by its type.


1 Answers

You should make the event nullable, because it is indeed nullable. It may look a bit strange but that's the correct way of expressing your intent.

It has always been necessary to check whether an event is null before raising it within the class. In this case nullable reference checking will warn you if you try to invoke it without checking for null.

    public class Publisher     {         public event EventHandler? IdleTimeoutReached;          protected virtual void RaiseIdleTimeoutEvent()         {             // `IdleTimeoutReached` will be null if no subscribers; compiler gives warning about possible null reference             IdleTimeoutReached.Invoke(this, EventArgs.Empty);              // No compiler warning             IdleTimeoutReached?.Invoke(this, EventArgs.Empty);         }     } 

The nullable annotation really only adds value for the class invoking the event. It won't affect callers at all because the += / -= syntax takes care of correctly assigning/removing those delegates.

So you should use:

public event EventHandler? IdleTimeoutReached; 

For events with EventArgs, use:

public event EventHandler<IdleTimeoutEventArgs>? IdleTimeoutReached; 
like image 142
Tobias J Avatar answered Oct 02 '22 15:10

Tobias J