The annotation for nullable reference types should only be used in code within a '#nullable' context

Mihail Shishkov picture Mihail Shishkov · Apr 3, 2019 · Viewed 44.5k times · Source

Just downloaded VS2019 and created a console app to try out the new C# 8 null reference types. Switched the project to build with lang ver C# 8 (currently showing as beta)

Then the following code results in a warning.

 class Program
    {
        static void Main(string[] args)
        {
            string? message = "Hello World";
            string message2 = null;

            Console.WriteLine(message);
            Console.WriteLine(message2);

            // The annotation for nullable reference types should only be used in code within a '#nullable' context
        }
    }

What does this actually mean?

Answer

Mihail Shishkov picture Mihail Shishkov · Apr 3, 2019

For anyone ending up here. You can put #nullable enable on top of the file for a file-by-file approach as suggested by @Marc in the comments.

You can also use combinations of #nullable enable/disable to annotate just parts of the file

class Program
{
    static void Main(string[] args)
    {
#nullable enable
        string? message = "Hello World";
#nullable disable
        string message2 = null;

        Console.WriteLine(message);
        Console.WriteLine(message2);
    }
}

Here's a link to the docs. https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#nullable-contexts

Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. The nullable annotation context of any given source line is either enabled or disabled. You can think of the pre-C# 8.0 compiler as compiling all your code in a disabled nullable context: any reference type may be null. The nullable warnings context may also be enabled or disabled. The nullable warnings context specifies the warnings generated by the compiler using its flow analysis.

The nullable annotation context and nullable warning context can be set for a project using the Nullable element in your .csproj file. This element configures how the compiler interprets the nullability of types and what warnings are generated. Valid settings are:

  • enable:
    • The nullable annotation context is enabled. The nullable warning context is enabled.
    • Variables of a reference type, string for example, are non-nullable. All nullability warnings are enabled.
  • warnings:
    • The nullable annotation context is disabled. The nullable warning context is enabled.
    • Variables of a reference type are oblivious. All nullability warnings are enabled.
  • annotations:
    • The nullable annotation context is enabled. The nullable warning context is disabled.
    • Variables of a reference type, string for example, are non-nullable. All nullability warnings are disabled.
  • disable:
    • The nullable annotation context is disabled. The nullable warning context is disabled.
    • Variables of a reference type are oblivious, just like earlier versions of C#. All nullability warnings are disabled.

In your .csproj file, simply add <Nullable>enable</Nullable> in the relevant <PropertyGroup> element (your project file may have separate <PropertyGroup> elements for each project configuration name).

So your project file should look like this one:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

To display the nullable messages as errors instead of warnings, add this to your project file:

<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>

...like so:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Nullable>enable</Nullable>
    <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
  </PropertyGroup>

</Project>

The corresponding full messages are:

  • CS8600: Converting null literal or possible null value to non-nullable type.
  • CS8602: Possible dereference of a null reference.
  • CS8603: Possible null reference return.

You can also use directives to set these same contexts anywhere in your project:

  • #nullable enable: Sets the nullable annotation context and nullable warning context to enabled.
  • #nullable disable: Sets the nullable annotation context and nullable warning context to disabled.
  • #nullable restore: Restores the nullable annotation context and nullable warning context to the project settings.
  • #nullable disable warnings: Set the nullable warning context to disabled.
  • #nullable enable warnings: Set the nullable warning context to enabled.
  • #nullable restore warnings: Restores the nullable warning context to the project settings.
  • #nullable disable annotations: Set the nullable annotation context to disabled.
  • #nullable enable annotations: Set the nullable annotation context to enabled.
  • #nullable restore annotations: Restores the annotation warning context to the project settings.

By default, nullable annotation and warning contexts are disabled. That means that your existing code compiles without changes and without generating any new warnings.

Note that pre-release versions of C# 8.0 and Visual Studio 2019 also supported safeonly, however this option has since been removed and is not present in the final shipping C# 8.0. Additionally the pre-release versions used #pragma warning restore nullable but the released version uses #nullable restore warnings.