【C#】null許容参照型の導入ガイド:NullReferenceExceptionを防ぐための設定と実装

目次

参照型における「null」の問題

C# 8.0より前では、stringやクラスなどの参照型は、デフォルトでnullを許容していました。そのため、開発者が意図せずnullの状態の変数にアクセスしてしまい、実行時にNullReferenceException(ぬるぽ)が発生するというバグが後を絶ちませんでした。

この長年の課題を解決するために導入されたのが「null許容参照型(Nullable Reference Types)」です。

この機能を有効にすると、参照型の変数はデフォルトで「null非許容(Non-Nullable)」として扱われるようになり、nullが入る可能性がある場合は明示的に?を付けて宣言する必要があります。これにより、コンパイラが事前にnullの可能性を検知し、警告を出してくれるようになります。

この記事では、null許容参照型の有効化方法から、具体的なコードでの書き方、警告の抑制方法までを解説します。


プロジェクトでの有効化

.NET 6以降の新しいプロジェクトテンプレートでは、デフォルトでこの機能が有効になっていますが、既存のプロジェクトや明示的に設定を確認する場合は、.csprojファイルを編集します。

<PropertyGroup>セクション内に<Nullable>enable</Nullable>を追加します。

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

型の定義:stringstring? の違い

機能を有効にすると、参照型の宣言方法が以下の2つに分かれます。

1. 非null許容参照型 (string)

単に string と書いた場合、その変数に null を代入することは許可されません。 初期化せずに使用したり、nullを代入しようとすると、コンパイラが警告を出します。

2. null許容参照型 (string?)

型名の後ろに ? を付けて string? と書いた場合、その変数には null を代入できます。 ただし、その変数にアクセス(.Lengthなど)する際は、事前にnullチェックを行わないと警告が出ます。


コード例:ユーザープロファイルの実装

「表示名(必須)」と「自己紹介(任意)」を持つユーザープロファイルクラスを例に、正しい実装方法を見ていきます。

using System;

public class UserProfile
{
    // 1. 非null許容プロパティ (string)
    // nullが入ることは想定されていないため、必ず初期値が必要。
    // コンストラクタで初期化しないと警告が出る。
    public string DisplayName { get; set; }

    // 2. null許容プロパティ (string?)
    // nullが入る可能性があるため、? を付ける。初期値は null で問題ない。
    public string? Bio { get; set; }

    // コンストラクタ
    public UserProfile(string name)
    {
        // DisplayName は非nullなので、ここで確実に値を設定する
        DisplayName = name;
    }
}

public class Program
{
    public static void Main()
    {
        // インスタンス生成
        var user = new UserProfile("Alice");

        // --- 非null許容型へのアクセス ---
        // DisplayName は null ではないことが保証されているため、
        // チェックなしで安全にアクセスできる。
        Console.WriteLine($"名前の長さ: {user.DisplayName.Length}");

        // 警告: 非null許容型に null を代入しようとすると警告が出る
        // user.DisplayName = null; 

        // --- null許容型へのアクセス ---
        user.Bio = null; // 代入はOK

        // 警告: nullの可能性があるため、直接アクセスすると警告が出る
        // Console.WriteLine(user.Bio.Length); 

        // 解決策1: nullチェックを行う
        if (user.Bio != null)
        {
            Console.WriteLine($"自己紹介の長さ: {user.Bio.Length}");
        }

        // 解決策2: null条件演算子 (?.) を使う
        Console.WriteLine($"自己紹介: {user.Bio ?? "(未設定)"}");
    }
}

出力結果:

名前の長さ: 5
自己紹介: (未設定)

null免除演算子 (!)

コンパイラの静的解析は優秀ですが、完璧ではありません。開発者側から見て「ここでは絶対にnullではない」とわかっている場面でも、コンパイラが警告を出してしまうことがあります。

そのような場合、変数の後ろに !(ビックリマーク)を付けることで、「これはnullではないので警告を無視してよい」とコンパイラに指示できます。これを「null免除演算子(Null-forgiving operator)」と呼びます。

コード例:! の使用

using System;

public class NullForgivingExample
{
    public static void Main()
    {
        string? message = GetMessage();

        // 論理上は null ではないとわかっているが、
        // 型が string? なので通常は警告が出る。
        // ! を付けて警告を抑制する。
        Console.WriteLine($"メッセージの長さ: {message!.Length}");
    }

    // 外部要因などで null を返す可能性があるシグネチャだが、
    // このテストケースでは確実に文字列を返すと仮定
    private static string? GetMessage()
    {
        return "Hello";
    }
}

注意: ! はあくまで「警告を消す」だけであり、実行時の動作を変えるものではありません。もし実際には null だった場合、当然ながら NullReferenceException が発生します。乱用は避け、本当に安全な場合のみ使用すべきです。


まとめ

null許容参照型を有効にすることで、コードの堅牢性が飛躍的に向上します。

  • 設定: .csproj<Nullable>enable</Nullable> を設定します。
  • Type: null を許容しません。初期化が必須です。
  • Type?: null を許容します。使用時にnullチェックが必須です。
  • var!: どうしても警告を消したい場合は ! で抑制します。

これらのルールに従ってコーディングすることで、コンパイル時に多くのnull関連エラーを検出し、実行時のクラッシュを未然に防ぐことができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次