【C#】null合体演算子(??)とnull合体割り当て(??=)の使い方:null判定を簡潔に記述する

目次

nullチェックの簡略化

プログラミングにおいて、「変数が null であればデフォルト値を使い、そうでなければ変数の値をそのまま使う」というロジックは頻繁に登場します。

例えば、ユーザーのニックネームが未設定(null)の場合に “Guest” という文字列を表示するようなケースです。これを従来の if-else 文や条件演算子(三項演算子 ?:)で記述すると、コードが冗長になりがちです。

string? userName = null;
string displayName;

// if-else を使った場合
if (userName != null)
{
    displayName = userName;
}
else
{
    displayName = "Guest";
}

// 条件演算子を使った場合
displayName = (userName != null) ? userName : "Guest";

C#では、このような「nullならこっち」という処理を簡潔に記述するために、null合体演算子 (??) が用意されています。

この記事では、?? 演算子の基本的な使い方と、C# 8.0で導入された null合体割り当て演算子 (??=) について解説します。


null合体演算子 (??) の基本

null合体演算子 ?? は、左側のオペランド(被演算子)が null でない場合はその値を返し、null である場合は右側のオペランドを評価して返します。

構文: 左側の値 ?? 右側の値(デフォルト値)

コード例:設定値の取得

ユーザーの設定ファイルパスを取得するロジックを例にします。カスタム設定パスが指定されていればそれを使い、指定されていなければ(nullならば)デフォルトのパスを使用します。

using System;

public class NullCoalescingExample
{
    public static void Main()
    {
        // ユーザーが指定したパス(未指定の場合は null)
        string? userConfigPath = null;

        // デフォルトのパス
        string defaultConfigPath = @"C:\App\Config\default.json";

        // --- null合体演算子 (??) の使用 ---
        // userConfigPath が null なので、defaultConfigPath が採用される
        string finalPath = userConfigPath ?? defaultConfigPath;

        Console.WriteLine($"使用する設定ファイル: {finalPath}");

        // --- 値が入っている場合 ---
        userConfigPath = @"D:\MyData\custom.json";
        
        // userConfigPath が null ではないので、userConfigPath が採用される
        finalPath = userConfigPath ?? defaultConfigPath;

        Console.WriteLine($"使用する設定ファイル: {finalPath}");
    }
}

出力結果:

使用する設定ファイル: C:\App\Config\default.json
使用する設定ファイル: D:\MyData\custom.json

このように、?? を使用することで、意図が明確になりコードが非常に短くなります。


null合体演算子のチェーン(連鎖)

?? 演算子は連鎖させることができます。複数の変数を順番にチェックし、最初に見つかった「非null」の値を取得する場合に便利です。

string? inputName = null;
string? storedName = null;
string defaultName = "No Name";

// inputName が null なら storedName をチェック
// storedName も null なら defaultName を採用
string displayName = inputName ?? storedName ?? defaultName;

Console.WriteLine(displayName); // "No Name"

null合体割り当て演算子 (??=)

C# 8.0からは、null合体割り当て演算子 (??=) が利用可能です。 これは、「変数が null の場合にのみ、右側の値を代入する」という操作を行います。

構文: 変数 ??= 値;

これは以下のコードと等価です。

if (変数 is null)
{
    変数 = 値;
}

コード例:遅延初期化(Lazy Initialization)

リストなどのオブジェクトを使用する直前に、まだ生成されていなければ(nullであれば)生成する、といった初期化処理に最適です。

using System;
using System.Collections.Generic;

public class NullCoalescingAssignmentExample
{
    public static void Main()
    {
        List<string>? errors = null;

        // errors が null なので、新しい List<string> を作成して代入する
        errors ??= new List<string>();

        errors.Add("Error 1: Connection failed.");
        Console.WriteLine($"エラー数: {errors.Count}");

        // この時点では errors は null ではない (インスタンスが存在する)
        // そのため、右側の new List<string>() は評価されず、代入も行われない
        errors ??= new List<string>();

        errors.Add("Error 2: Timeout.");
        Console.WriteLine($"エラー数: {errors.Count}"); // カウントは増えている
    }
}

出力結果:

エラー数: 1
エラー数: 2

まとめ

?? および ??= 演算子は、C#におけるnull処理を劇的に簡潔にする機能です。

  • val ?? default: valnull のときに default を返します。値の取得や表示に使用します。
  • val ??= newValue: valnull のときに newValue を代入します。遅延初期化やデフォルト値の設定に使用します。

これらの演算子を積極的に利用することで、if (x == null) のような定型的な記述を減らし、ビジネスロジックの本質的な部分に集中できるようになります。

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

この記事を書いた人

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

目次