Skip to content

Nullable Reference Types (NRT)

Joseph Madamba edited this page Mar 3, 2024 · 5 revisions

Nullable reference types (NRT) are enabled by default for this project. Some files, originally authored prior to enabling NRT, are marked #nullable disable to disable null checking.

Important

NRT should be enabled for new files.

The usage of the null-forgiving operator is generally discouraged except for test code and special cases described below. If eliding the nullability at runtime is unavoidable, use Debug.Assert() instead, or the .AsNonNull() extension method provided by framework.

Dependency injection considerations

The compiler will complain if a Resolved field of a non-nullable reference type is not initialized in the constructor. However, the field is non-nullable during the lifetime of the Drawable, after dependency injection has taken place. We use NRT for a such field, and initialize it by null! (null-forgiving operator applied to null).

-#nullable disable

 public partial class MyClass : Drawable
 {
      [Resolved]
-     private ISkinSource skin { get; set; }
+     private ISkinSource skin { get; set; } = null!;

      // ...
 }

However, that pattern introduces nullability false-positives. For example, in a Dispose() method, a Resolved field may be null because the Drawable can be disposed after failing to load.

In that case, use x.IsNotNull() from osu.Framework.Extensions.ObjectExtensions to suppress warning:

         public void Dispose()
         {
-            if (skin != null)
+            if (skin.IsNotNull())
             {
                 // ...
             }
         }

For nullable/optional dependencies, Resolved automatically sets CanBeNull = true for a nullable reference type.

-        [Resolved(CanBeNull = true)]
-        private EditorBeatmap editorBeatmap { get; set; }
+        [Resolved]
+        private EditorBeatmap? editorBeatmap { get; set; }

The same applies to BDL methods:

-        [BackgroundDependencyLoader(true)]
-        private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour osuColour)
+        [BackgroundDependencyLoader]
+        private void load(OverlayColourProvider? colourProvider, OsuColour osuColour)