Object reference not set エラー(null参照)の原因
C#で最も有名な実行時エラーです。nullのままの変数のメンバーにアクセスしようとすると発生します。
エラーメッセージの読み方
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
System- 名前空間 — System なら標準の基本例外です
NullReferenceException- 例外クラス — 何が起きたか。ここを検索するのが最短です
Object reference not set to an instance of an object.- 詳細メッセージ — どの値が問題だったか
at Program.Main(String[] args) in Program.cs:line 4- 発生箇所 — スタックトレースの先頭行
このエラーが出る典型パターン
パターン1
1 class Program { 2 static void Main(string[] args) { 3 string s = null ; ^ 4 System.Console.WriteLine(s.Length); 5 } 6 }
sがnullのままLengthにアクセスしています。nullは「何もない」ことを表す値で、メンバーを持ちません。
直し方: null を "hi" にします。
パターン2
1 class Program { 2 static void Main(string[] args) { 3 string[] names = new string[3]; 4 names[0] = null ; ^ 5 System.Console.WriteLine(names[0].ToUpper()); 6 } 7 }
string配列は要素をnullで初期化します。代入し忘れた要素をそのまま使うとNullReferenceExceptionになります。
直し方: null を "Al" にします。
パターン3
1 class Program { 2 static string Find(bool ok) { 3 if (ok) return "yes"; 4 return null; ^ 5 } 6 static void Main(string[] args) { 7 string r = Find(false); 8 System.Console.WriteLine(r.Length); 9 } 10 }
メソッドがnullを返す経路があると、呼び出し側でチェックせずに使った瞬間に例外が起きます。
直し方: null を "no" にします。
パターン4
1 class Program { 2 static void Main(string[] args) { 3 string msg = null ; ^ 4 System.Console.WriteLine(msg.Length); 5 } 6 }
msgがnullのままLengthにアクセスするとNullReferenceExceptionになります。
直し方: null を "go" にします。
パターン5
1 class Program { 2 static string Lookup(bool found) { 3 if (found) return "item"; 4 return null ; ^ 5 } 6 static void Main(string[] args) { 7 string r = Lookup(false); 8 System.Console.WriteLine(r.Length); 9 } 10 }
メソッドがnullを返す経路があると、呼び出し側でチェックせず使った瞬間に例外になります。
直し方: null を "none" にします。
よくある誤解
nullは「何もない」ことを表す値そのもので、メンバーを持ちません。宣言しただけの参照型変数や、代入し忘れた配列の要素はnullのままです。
実務での勘所
この例外の設計上の根本原因(nullを許すあらゆる参照型変数)は、null参照の発明者であるTony Hoare自身が後年「10億ドルの失敗」と呼んで悔いたことで有名です。C# 8以降はNullable Reference Typesという機能(プロジェクトで#nullable enableを設定)により、string(null不可のつもり)とstring?(nullを許容)を型として区別できるようになり、null非許容の変数にnullを代入しようとするコードをコンパイル時の警告として検出できます。実行時まで待たずに、この種のミスの多くを事前に見つけられるようになりました。
関連するエラー
- Index was outside the bounds of the array の原因と直し方配列やリストの範囲外アクセスで実行時に発生します。
- static文脈からインスタンスメンバーへアクセスした原因staticなMainからインスタンスメンバーへ直接アクセスしようとしたときに出ます。