• システム開発に関わる内容をざっくりと書いていく

ArgumentNullException と NullReferenceException の使い分け

ArgumentNullExceptionNullReferenceException は、どちらも「null」が絡む例外だが、意味も出し方も違う

現場では「どっちを投げればいい?」「どっちが落ちた?」で迷いやすいので、ざっくり使い分けを整理する。


先に結論

  • ArgumentNullException呼び出し側が渡した引数が null。メソッドの入り口で明示的に投げる
  • NullReferenceExceptionnull の参照にメンバーアクセスした。実行時にフレームワーク/ランタイムが投げることが多い
  • 公開 API の引数チェックは ArgumentNullException(または ArgumentNullException.ThrowIfNull
  • 自分のフィールド/戻り値が null だったせいで落ちたなら、まず設計と初期化を疑う(NRE を握りつぶさない)

一言で言うと

  • ArgumentNullException = 「お前が渡した null が悪い」(契約違反・呼び出し側の責任)
  • NullReferenceException = 「null のまま触った」(多くの場合、実装側の想定漏れ)

ArgumentNullException を使うとき

メソッド/コンストラクタの引数が null だと先に進めないとき。入り口で落とす。

public void Send(string to, string body)
{
    ArgumentNullException.ThrowIfNull(to);
    ArgumentNullException.ThrowIfNull(body);
    // ...
}

古い書き方:

if (to is null)
    throw new ArgumentNullException(nameof(to));

向いている場面

  • ライブラリ/公開メソッドの契約
  • コンストラクタ注入の依存が null
  • 「null を許さない」パラメータのガード

NullReferenceException が起きるとき

null 参照に対して . でメンバーアクセスしたとき。自分で throw new NullReferenceException() することはほぼない(してはいけない寄り)。

User? user = FindUser(id); // 見つからず null
Console.WriteLine(user.Name); // NullReferenceException

詳細な発生パターンは NullReferenceException の記事 を参照。


よくある迷いどころ

1. 戻り値が null だったとき、何を投げる?

「必須のはずの取得が null」なら、InvalidOperationException や独自例外の方が意味が伝わることが多い。NullReferenceException を自分で投げる必要はない。

var user = repo.Find(id)
    ?? throw new InvalidOperationException($"User {id} was not found.");

2. 引数が null なのに NRE で落ちる

ガードせずにそのまま触ると NRE になる。呼び出し側から見ると「契約違反なのに NRE」で分かりにくい。公開 API なら入り口で ArgumentNullException

3. nullable 参照型との関係

  • string(非 null)引数なのに実行時 null が来る → 入り口で ArgumentNullException
  • string? を許すなら、使う直前で分岐する(NRE を出さない)

切り分けの目安

  • 例外メッセージに引数名(Parameter name: xxx)がある → ArgumentNullException。呼び出し元の渡し方を疑う
  • スタックトレースの行が foo.Bar のようなメンバーアクセス → NRE。その行の左辺が null
  • ライブラリ境界で落ちた → まず引数ガードの有無を確認

ざっくりまとめ

  • 引数の null は ArgumentNullException
  • null 参照へのアクセスは NullReferenceException(多くの場合バグ)
  • 公開 API は入り口でガード。NRE まで到達させない
  • 「見つからない」は NRE ではなく、意図の伝わる例外/null 許容設計で返す