条件付き代入の簡略化
プログラミングにおいて、「変数がまだ初期化されていない(nullである)場合に限り、初期値やデフォルト値を代入したい」というロジックは頻繁に登場します。
従来、この処理はif文を使用して記述されてきましたが、C# 8.0で導入された「null合体割り当て演算子(??=)」を使用することで、より簡潔かつ直感的に記述できるようになりました。
この記事では、??=演算子の基本的な使い方と、従来の方法との違い、そして実用的なメリットについて解説します。
null合体割り当て演算子 (??=) とは
??= 演算子は、左側の変数が null である場合にのみ、右側の値を評価して代入します。左側の変数が null でない場合、右側の値は評価されず、代入も行われません。
構文: 変数 ??= 値;
これは、以下のコードとほぼ同等の意味を持ちます。
if (変数 is null)
{
変数 = 値;
}
コード例1:基本的なデフォルト値の設定
ユーザーからのコメント入力処理を例にします。コメントが未入力(null)の場合に、自動的にデフォルトのメッセージを設定するコードです。
using System;
public class DefaultValueExample
{
public static void Main()
{
// ケース1: コメントが null の場合
string? userComment = null;
// userComment が null なので、"No comment provided." が代入される
userComment ??= "No comment provided.";
Console.WriteLine($"コメント1: {userComment}");
// ケース2: コメントが既に存在する場合
string? existingComment = "Great post!";
// existingComment は null ではないため、右辺は評価されず、代入も行われない
existingComment ??= "No comment provided.";
Console.WriteLine($"コメント2: {existingComment}");
}
}
出力結果:
コメント1: No comment provided.
コメント2: Great post!
従来の方法 (if文) との比較
??= 演算子が導入される前は、同様の処理を行うために if 文によるチェックが必要でした。
従来の書き方
string? categoryName = null;
if (categoryName == null)
{
categoryName = "Uncategorized";
}
??= を使った書き方
string? categoryName = null;
categoryName ??= "Uncategorized";
??= を使用することで、コードの行数が削減されるだけでなく、「nullの場合に初期化する」という意図がより明確になります。
コード例2:リストの遅延初期化(Lazy Initialization)
??= 演算子の真価が発揮されるのは、リストやオブジェクトの「遅延初期化」を行う場面です。
オブジェクトを最初から生成するのではなく、「必要になった瞬間(変数がまだnullの時)」に生成することで、メモリ使用量を節約し、パフォーマンスを向上させるパターンです。
using System;
using System.Collections.Generic;
public class SearchQuery
{
// 初期状態は null (メモリを確保しない)
public List<string>? SearchTags { get; private set; }
public void AddTag(string tag)
{
// SearchTags が null の場合のみ、新しい List<string> を生成して代入
// すでに生成されていれば、そのまま使用する
SearchTags ??= new List<string>();
SearchTags.Add(tag);
Console.WriteLine($"タグを追加しました: {tag}");
}
}
public class Program
{
public static void Main()
{
var query = new SearchQuery();
// まだ SearchTags は null
Console.WriteLine($"初期状態: {query.SearchTags is null}");
// 初めてタグを追加 (ここで List が生成される)
query.AddTag("C#");
// 2回目は既存の List が使われる (再生成されない)
query.AddTag("Programming");
Console.WriteLine($"タグの数: {query.SearchTags?.Count}");
}
}
出力結果:
初期状態: True
タグを追加しました: C#
タグを追加しました: Programming
タグの数: 2
この例では、SearchTags プロパティは最初は null です。AddTag メソッドが呼ばれたときに初めて new List<string>() が実行されます。??= を使うことで、このロジックを1行で記述できています。
まとめ
null合体割り当て演算子(??=)は、変数が null のときだけ値を代入するための演算子です。
- 簡潔性:
if (x == null) x = y;をx ??= y;と短く記述できます。 - 効率性: 左辺が
nullでない場合、右辺の処理(オブジェクト生成など)は実行されないため、パフォーマンス上の無駄がありません。 - 用途: デフォルト値の設定や、コレクションの遅延初期化に最適です。
