noxi雑記

.NET、Angularまわりの小ネタブログ

C# 8.0のNull許容参照型を有効にする

先日 .NET Core 3.0 がリリースされ、同時に C# 8.0 もリリースされました。色々と先行き不安なところはありつつも、C# 8.0 最大の変更点は参照型が null なり得るかどうかをコード上で明示できる Null許容参照型 の機能でしょう。 Kotlin や TypeScript など、他の言語には既に存在する機能です。また ReSharper が導入された Visual Studio や Rider では JetBrains Annotation を使用することで擬似的ではありますが、非nullを明示することができました。

今回は機能を有効にしたときの文法ではなく、そもそも機能を有効にする方法をメモします。2019年10月現在、Null許容参照型機能を Visual Studio の設定画面から有効にすることはできません。


部分的に有効にする

Null許容参照型を特定のファイルや行に対して有効にするには、 #nullable ディレクティブを使用します。取り得る値は enable disable restore の3つです。

効果
enable このディレクティブ以降、Null許容参照型の機能を有効に変更します。
disable このディレクティブ以降、Null許容参照型の機能を無効に変更します。
restore このディレクティブ以降、Null許容参照型の機能をプロジェクトのデフォルト値に変更します。
class Program
{
    static void Main(string[] args)
    {

// これ以降Null許容参照型 ON
#nullable enable

        string? nullable = null;
        if (nullable?.Length == 0)
        {
            Console.WriteLine("never");
        }
    }
}

プロジェクト全体に対して有効にする

プロジェクト全体に対して有効に設定するには csproj の <PropertyGroup><Nullable> タグを追加します。

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <LangVersion>8.0</LangVersion>

    <!-- プロジェクト全体を有効に設定 -->
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Null許容参照型の適用種類

Null許容参照型には2つのコンテキストが存在します。1つは文法の有効可否です。 #nullable enable annotations を付与することでNull許容参照型の文法のみを有効にすることができます。もう1つが警告の出力有無です。こちらは #nullable enable warnings とすることでコンパイラーが分かる範囲で警告を出力してくれます。

警告のみ有効の場合

class Program
{
    static void Main(string[] args)
    {
#nullable enable warnings
        string nullable = null;
        if (nullable.Length == 0)  // 警告 CS8602 null 参照の可能性があるものの逆参照です。
        {
            Console.WriteLine("never");
        }
    }
}

文法のみ有効の場合

class Program
{
    static void Main(string[] args)
    {
#nullable enable annotations
        string nullable = null;
        if (nullable.Length == 0)  // 特に警告は出ないがここでNullReferenceException
        {
            Console.WriteLine("never");
        }
   }
}

文法、警告共に有効の場合

class Program
{
    static void Main(string[] args)
    {
#nullable enable
        string nullable = null;    // 警告 CS8600 Null リテラルまたは Null の可能性がある値を Null 非許容型に変換しています。
        if (nullable.Length == 0)  // 警告 CS8602 null 参照の可能性があるものの逆参照です。
        {
            Console.WriteLine("never");
        }
    }
}