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

81,336

Solution 1

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.

Solution 2

I got this same error too, and I spent a few days fighting it, for a reason not described by the other answers: There are special (undocumented?) rules in the Roslyn C# compiler for generated code that uses the nullable feature, and until I upgraded Visual Studio 2019 to the latest version (16.4+), the error message was exactly the same unhelpful message as above — despite having <Nullable>enabled</Nullable> in my project file.

But in the latest versions of Visual Studio 2019, they've upgraded the error message to this:

warning CS8669: The annotation for nullable reference types should only be used in code within a ‘#nullable’ annotations context. Auto-generated code requires an explicit ‘#nullable’ directive in source.

(Emphasis added to the newly-added part of the error message.)

So if you're seeing this error message in any .generated.cs files you're emitting, those files need to have #nullable enable added to them explicitly — Roslyn apparently always ignores the project-level <Nullable>enable</Nullable> setting for generated code.

Share:
81,336
Mihail Shishkov
Author by

Mihail Shishkov

Updated on December 10, 2021

Comments

  • Mihail Shishkov
    Mihail Shishkov over 2 years

    I have a console app to try out the C# 8 null reference types. Switched the project to build with lang ver C# 8.

    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?

  • Marc Gravell
    Marc Gravell about 5 years
    nice answer; I like that it covers both approaches
  • Damien_The_Unbeliever
    Damien_The_Unbeliever about 5 years
    Might also be worth expanding to cover #nullable disable and #nullable restore or a link to documentation covering all of them.
  • Drew Noakes
    Drew Noakes about 5 years
    Answer edited to reflect the renaming of property NullableContextOptions to Nullable in VS 16.1.
  • DJ-Glock
    DJ-Glock about 5 years
    Good answer. But for some reason approach with changing project parameters does not work for me. Using Visual Studio Code.
  • Dai
    Dai over 4 years
    Apparently the safeonly option is no-longer defined: github.com/dotnet/docs/issues/13227
  • yas17
    yas17 about 4 years
    I got Named attribute argument expected ERROR when using <Nullable>enable</Nullable>
  • Eduard Grinberg
    Eduard Grinberg about 4 years
    nice answer. I would add CS8618 to warnings as errors to cover: "Non-nullable property 'PbxUniqueCallId' is uninitialized. Consider declaring the property as nullable."
  • Christian Findlay
    Christian Findlay almost 4 years
    I have this in my csproj so I shouldn't need to put anything extra in the code <Nullable>enable</Nullable> but I still get the error
  • kodybrown
    kodybrown over 3 years
    amazingly thorough answer!
  • Bill Menees
    Bill Menees over 3 years
    The documentation for C#'s nullable contexts for generated files is under docs.microsoft.com/en-us/dotnet/csharp/…. They've added an "Important" subsection that lists the 4 ways a file is marked as generated.
  • Sean Werkema
    Sean Werkema over 3 years
    Thanks for the link, and that's a good find! It's good that they've finally added the documentation; but it's bad that it was a completely-undocumented "magic" rule for several years prior.
  • Erik Hart
    Erik Hart over 2 years
    I also got the CS8632 warning even in a newly created .NET 6.0 project, own code, within an older solution that doesn't use the C#8 nullable reftypes. The new project has <Nullable>enable</Nullable> set. Solution: delete all bin and obj directories in the solution, as also recommended for net6 migration by MS. "Clean Solution" was not sufficient in my case.
  • Paul Ruane
    Paul Ruane over 2 years
    The nullable directive can also now be defined for all projects in a directory using Directory.Build.props, see blog.johnnyreilly.com/2021/07/14/…
  • cguedel
    cguedel about 2 years
    any idea why this is like this?