C#のToStringでnullはどうなる?例外の原因と安全な文字列変換方法を解説

はじめに

C#で文字列変換を行うとき、よく使われるのがToString()です。しかし、対象の値がnullだった場合に「ToString()はどうなるのか」「なぜ例外が発生するのか」でつまずくことがあります。

結論からいうと、null参照に対してToString()を呼び出すと、NullReferenceExceptionが発生します。ToString()nullを返すのではなく、そもそもnullにはメソッドを呼び出せないためです。

この記事では、C#のToString()nullを扱ったときの挙動、例外の原因、安全な文字列変換方法、Convert.ToString()との違い、実務で使いやすい書き方まで解説します。

1. C#のToStringでnullはどうなる?

1-1. 結論:null参照にToString()を呼ぶとNullReferenceExceptionになる

C#では、変数の中身がnullの状態でToString()を呼び出すと、実行時にNullReferenceExceptionが発生します。

C#
string value = null;
string text = value.ToString();

このコードはコンパイルできる場合がありますが、実行すると例外になります。

ToString()はオブジェクトに対して呼び出すメソッドです。nullはオブジェクトの実体を参照していない状態なので、メソッドを呼ぶ対象が存在しません。

1-2. string型がnullの場合のサンプルコードと実行結果

C#
string value = null;

Console.WriteLine(value.ToString());

実行結果は次のようになります。

System.NullReferenceException: Object reference not set to an instance of an object.

string型であっても、値がnullならToString()は呼び出せません。

1-3. object型がnullの場合のサンプルコードと実行結果

C#
object value = null;

Console.WriteLine(value.ToString());

こちらも同じくNullReferenceExceptionになります。

System.NullReferenceException: Object reference not set to an instance of an object.

object型の変数であっても、実体がnullならメソッド呼び出しはできません。

1-4. 「ToString()がnullを返す」のではなく「nullにメソッドを呼べない」が原因

重要なのは、ToString()nullを返しているわけではないという点です。

C#
value.ToString()

この処理では、まずvalueという参照先のオブジェクトを探します。しかしvaluenullの場合、参照先が存在しません。そのため、ToString()の処理に入る前に例外が発生します。

1-5. null・空文字・"null"という文字列の違い

null、空文字、"null"はそれぞれ意味が異なります。

C#
string a = null;      // 値が存在しない
string b = ""; // 長さ0の文字列
string c = "null"; // n,u,l,l の4文字

nullは「何も参照していない状態」です。空文字は「文字数が0の文字列」です。"null"は通常の文字列です。

この違いを理解していないと、画面表示、DB保存、CSV出力、JSON変換などで意図しない結果になることがあります。

2. ToString()でNullReferenceExceptionが発生する原因

2-1. ToString()はインスタンスメソッドである

ToString()は、多くの型で使えるメソッドですが、基本的にはインスタンスに対して呼び出すメソッドです。

C#
var number = 123;
var text = number.ToString();

この場合、numberという値に対してToString()を呼び出しています。

一方で、次のように参照先がない場合は呼び出せません。

C#
object value = null;
value.ToString();

2-2. nullはオブジェクトの実体を参照していない状態

nullは「空の文字列」ではありません。オブジェクトが存在しない状態です。

C#
string value = null;

この変数には文字列オブジェクトが入っていません。そのため、value.ToString()のようにメソッドを呼び出そうとすると、実行時エラーになります。

2-3. コンパイルは通るのに実行時エラーになる理由

C#では、変数の型がstringobjectであれば、その型にToString()メソッドが存在するため、コード自体はコンパイルできる場合があります。

しかし、実際に実行したときの値がnullであれば、参照先のオブジェクトが存在しないため例外になります。

つまり、コンパイル時には「型としてToString()を呼べるか」が確認され、実行時には「実際に参照先があるか」が問題になります。

2-4. nullable reference types有効時の警告との関係

C# 8.0以降では、nullable reference typesを有効にすると、nullの可能性がある参照に対して警告が出ることがあります。

C#
#nullable enable

string? value = null;
string text = value.ToString();

このようなコードでは、valuenullの可能性があるため、警告が表示されます。

安全に書くなら次のようにします。

C#
string? value = null;
string text = value?.ToString() ?? "";

nullable reference typesは、NullReferenceExceptionをコンパイル時に完全に防ぐものではありませんが、危険なコードに気づきやすくなります。

2-5. よくあるエラーメッセージと読み方

よく見るエラーメッセージは次のようなものです。

System.NullReferenceException: Object reference not set to an instance of an object.

これは「オブジェクト参照がオブジェクトのインスタンスに設定されていない」という意味です。

簡単にいうと、「nullの変数に対してメソッドやプロパティを使おうとした」ということです。

3. nullでも安全に文字列変換する方法

3-1. null条件演算子:value?.ToString()

nullの可能性がある値に対して安全にToString()を呼びたい場合は、null条件演算子?.を使えます。

C#
string? value = null;
string? text = value?.ToString();

valuenullの場合、value?.ToString()の結果はnullになります。例外は発生しません。

3-2. null合体演算子:value?.ToString() ?? ""

nullの場合に空文字へ変換したいなら、??を組み合わせます。

C#
string? value = null;
string text = value?.ToString() ?? "";

または次のようにstring.Emptyを使ってもよいです。

C#
string text = value?.ToString() ?? string.Empty;

この書き方は、nullを空文字として扱いたい場面でよく使われます。

3-3. Convert.ToString(value)を使う方法

Convert.ToString()を使う方法もあります。

C#
object? value = null;
string? text = Convert.ToString(value);

Convert.ToString(object?)は、引数がnullの場合に空文字を返します。

C#
object? value = null;
Console.WriteLine(Convert.ToString(value) == "");

実行結果は次のようになります。

True

ただし、オーバーロードによって挙動が異なる場合があるため、string?を扱うときは注意が必要です。

3-4. string.Emptyをデフォルト値にする方法

空文字を明示したい場合は、string.Emptyを使うと意図が伝わりやすくなります。

C#
string text = value?.ToString() ?? string.Empty;

""でも動作は同じですが、プロジェクトのコーディング規約によってはstring.Emptyが好まれることもあります。

3-5. 任意の代替文字列を返す方法

画面表示などで、nullの場合に「未設定」や「なし」と表示したい場合は、代替文字列を指定します。

C#
string text = value?.ToString() ?? "未設定";

たとえばユーザー名が未入力の場合に、次のように表示できます。

C#
Console.WriteLine(user.Name?.ToString() ?? "未設定");

3-6. if文でnullチェックしてからToString()する方法

シンプルにif文でチェックする方法もあります。

C#
string text;

if (value == null)
{
text = "";
}
else
{
text = value.ToString();
}

処理が複雑な場合や、nullの場合だけ特別なログを出したい場合は、if文のほうが読みやすいこともあります。

4. ToString()とConvert.ToString()の違い

4-1. ToString()はnull参照で例外になる

ToString()は対象のインスタンスに対して呼び出すため、対象がnullなら例外になります。

C#
object? value = null;
string text = value.ToString(); // NullReferenceException

安全に使うには、事前にnullチェックする必要があります。

4-2. Convert.ToString(object)はnullを空文字として扱える

Convert.ToString(object?)は、引数がnullの場合に空文字を返します。

C#
object? value = null;
string? text = Convert.ToString(value);

Console.WriteLine(text == ""); // True

objectとして受け取った値を安全に文字列化したい場合に便利です。

4-3. Convert.ToString(string)ではnullがそのまま返る場合がある

注意したいのは、Convert.ToString()には複数のオーバーロードがあることです。

C#
string? value = null;
string? text = Convert.ToString(value);

この場合、Convert.ToString(string?)が呼ばれ、結果はnullになる場合があります。

一方で、次のようにobjectとして渡すと空文字になります。

C#
string? value = null;
string? text = Convert.ToString((object?)value);

この違いは混乱しやすいため、nullを空文字にしたい場合は次の書き方が明確です。

C#
string text = value ?? string.Empty;

または、

C#
string text = value?.ToString() ?? string.Empty;

4-4. どちらを使うべきか判断する基準

ToString()Convert.ToString()は、目的によって使い分けるとよいです。

値がnullではないと分かっている場合は、ToString()で問題ありません。

C#
int number = 123;
string text = number.ToString();

nullの可能性がある場合は、?.ToString() ?? ""のように安全な書き方を使うのがおすすめです。

C#
string text = value?.ToString() ?? string.Empty;

object型の値をまとめて文字列化したい場合は、Convert.ToString(value)も選択肢になります。

4-5. 可読性・安全性・意図の伝わりやすさの比較

実務では、単に動くかどうかだけでなく、コードを読んだ人に意図が伝わるかも重要です。

C#
string text = value?.ToString() ?? string.Empty;

このコードは「valuenullなら空文字にする」という意図が明確です。

一方で、

C#
string? text = Convert.ToString(value);

は短く書けますが、型やオーバーロードによって結果の解釈に注意が必要です。

迷った場合は、?.ToString() ?? string.Emptyのように明示的な書き方を選ぶと安全です。

5. 型別に見るnullとToString()の挙動

5-1. string型のnullをToString()した場合

C#
string? value = null;
string text = value.ToString();

このコードはNullReferenceExceptionになります。

string型であっても、nullなら文字列オブジェクトが存在しないためです。

安全に書くなら次のようにします。

C#
string text = value ?? string.Empty;

string型の場合、すでに文字列なのでToString()を呼ぶ必要がないことも多いです。

5-2. object型のnullをToString()した場合

C#
object? value = null;
string text = value.ToString();

こちらもNullReferenceExceptionになります。

安全に書くなら次のようにします。

C#
string text = value?.ToString() ?? string.Empty;

または、

C#
string? text = Convert.ToString(value);

5-3. int?やDateTime?などNullable型のToString()

int?DateTime?などのNullable型では、少し挙動が異なります。

C#
int? number = null;
string text = number.ToString();

Console.WriteLine(text == ""); // True

Nullable<T>.ToString()は、値がない場合に空文字を返します。そのため、int?DateTime?の変数自体に対するToString()では、通常の参照型のようなNullReferenceExceptionにはなりません。

C#
int? number = 123;
Console.WriteLine(number.ToString()); // 123

ただし、Nullable型をobjectに代入した場合などは挙動を正しく理解しておく必要があります。

5-4. DataTableやDB取得値でDBNullが含まれる場合

データベースから値を取得する場合、nullではなくDBNull.Valueが入ることがあります。

C#
object value = row["Name"];

この値がDBNull.Valueの場合、value.ToString()は例外にはならず、空文字のように見える結果になることがあります。

しかし、DBNull.ValueはC#のnullとは別物です。

安全に扱うなら次のように判定します。

C#
string text = value == DBNull.Value ? string.Empty : value?.ToString() ?? string.Empty;

DBの値を扱う場合は、nullだけでなくDBNull.Valueも考慮しましょう。

5-5. クラスのプロパティがnullの場合

クラスのプロパティがnullの場合も注意が必要です。

C#
class User
{
public string? Name { get; set; }
}

var user = new User();
string name = user.Name.ToString();

user自体はnullではありませんが、NamenullなのでNullReferenceExceptionになります。

安全に書くなら次のようにします。

C#
string name = user.Name ?? string.Empty;

また、user自体もnullの可能性があるなら次のようにします。

C#
string name = user?.Name ?? string.Empty;

5-6. LINQやDTO変換で起きやすいnull例外

LINQやDTO変換では、プロパティのnullを見落としてToString()を呼んでしまうことがあります。

C#
var dtoList = users.Select(x => new UserDto
{
Name = x.Name.ToString()
}).ToList();

x.Namenullの場合、このコードは例外になります。

安全に書くなら次のようにします。

C#
var dtoList = users.Select(x => new UserDto
{
Name = x.Name ?? string.Empty
}).ToList();

数値や日付のNullable型なら次のように書けます。

C#
Date = x.Birthday?.ToString("yyyy/MM/dd") ?? string.Empty

6. 実務でよく使う安全な書き方

6-1. 空文字に変換したい場合

nullを空文字にしたい場合は、次の書き方が分かりやすいです。

C#
string text = value?.ToString() ?? string.Empty;

対象がstring?なら、ToString()は不要です。

C#
string text = value ?? string.Empty;

6-2. nullのまま保持したい場合

nullを空文字に変換せず、nullのまま保持したい場合は、次のようにします。

C#
string? text = value?.ToString();

この場合、valuenullならtextnullになります。

DB保存やJSON出力などで、nullと空文字を区別したい場合に使います。

6-3. 画面表示用に「未設定」などを出したい場合

画面表示では、nullや未入力の値をそのまま出すより、「未設定」などの文字列に変換したほうが親切な場合があります。

C#
string displayName = user.Name ?? "未設定";

空文字も未設定扱いにしたい場合は、string.IsNullOrEmptyを使います。

C#
string displayName = string.IsNullOrEmpty(user.Name) ? "未設定" : user.Name;

空白だけの文字列も未設定扱いにするなら、string.IsNullOrWhiteSpaceを使います。

C#
string displayName = string.IsNullOrWhiteSpace(user.Name) ? "未設定" : user.Name;

6-4. ログ出力で例外を避けたい場合

ログ出力では、ログを書こうとして例外が発生するのは避けたいところです。

C#
logger.LogInformation("Value: {Value}", value?.ToString() ?? "(null)");

また、文字列補間を使う場合は次のように書けます。

C#
Console.WriteLine($"Value: {value}");

文字列補間では、nullが空文字として扱われる場面があります。ただし、明確に(null)と出したいなら次のようにします。

C#
Console.WriteLine($"Value: {value?.ToString() ?? "(null)"}");

6-5. CSV・JSON・フォーム送信で安全に変換したい場合

CSVやフォーム送信では、nullを空文字にしたいことがよくあります。

C#
string csvValue = value?.ToString() ?? string.Empty;

ただし、JSONではnullと空文字は意味が異なります。

JSON
{
"name": null
}

と、

JSON
{
"name": ""
}

は別のデータです。

API仕様でnullを許可しているのか、空文字に変換すべきなのかを確認してから変換しましょう。

6-6. 拡張メソッドで共通化する方法

プロジェクト内で何度も同じ変換を書く場合は、拡張メソッドにする方法もあります。

C#
public static class ObjectExtensions
{
public static string ToSafeString(this object? value)
{
return value?.ToString() ?? string.Empty;
}
}

使う側は次のように書けます。

C#
string text = value.ToSafeString();

代替文字列を指定できるようにするなら、次のようにします。

C#
public static class ObjectExtensions
{
public static string ToSafeString(this object? value, string defaultValue)
{
return value?.ToString() ?? defaultValue;
}
}

使用例です。

C#
string text = value.ToSafeString("未設定");

7. null対応で注意したい落とし穴

7-1. value.ToString() ?? ""では例外を防げない

よくある間違いが次の書き方です。

C#
string text = value.ToString() ?? "";

このコードでは、valuenullの場合、??に到達する前にvalue.ToString()で例外が発生します。

安全にするには、次のように?.を使います。

C#
string text = value?.ToString() ?? "";

7-2. ?.ToString()の結果もnullになり得る

value?.ToString()は例外を防げますが、結果はnullになる可能性があります。

C#
string? text = value?.ToString();

空文字にしたい場合は、必ず??を組み合わせます。

C#
string text = value?.ToString() ?? string.Empty;

7-3. 空文字に変換するとnullと区別できなくなる

nullを空文字に変換すると、元の値がnullだったのか、もともと空文字だったのか区別できなくなります。

C#
string text = value ?? string.Empty;

画面表示では便利ですが、DB更新やAPI連携では注意が必要です。

たとえば「未設定」を表すnullと、「入力済みだが空」を表す空文字を区別する仕様の場合、安易に空文字へ変換するとデータの意味が変わってしまいます。

7-4. カスタムToString()の実装に注意する

自作クラスでToString()をオーバーライドする場合、内部プロパティがnullの可能性を考慮しましょう。

C#
public override string ToString()
{
return Name.ToString();
}

Namenullの場合、このコードは例外になります。

安全に書くなら次のようにします。

C#
public override string ToString()
{
return Name ?? string.Empty;
}

または、表示用の形式を明確にします。

C#
public override string ToString()
{
return Name ?? "未設定";
}

7-5. 日付や数値のToString()ではカルチャやフォーマットも考慮する

日付や数値をToString()する場合は、nullだけでなくフォーマットやカルチャにも注意が必要です。

C#
DateTime? date = DateTime.Now;
string text = date?.ToString("yyyy/MM/dd") ?? string.Empty;

数値の場合も、表示形式を指定できます。

C#
decimal? price = 1234.5m;
string text = price?.ToString("N2") ?? string.Empty;

多言語対応や固定フォーマットが必要な場合は、CultureInfoも検討します。

C#
using System.Globalization;

decimal? price = 1234.5m;
string text = price?.ToString("N2", CultureInfo.InvariantCulture) ?? string.Empty;

8. C#のToStringとnullに関するよくある質問

8-1. null.ToString()はなぜ使えない?

nullはオブジェクトの実体を参照していないためです。

ToString()はインスタンスに対して呼び出すメソッドなので、呼び出し対象が存在しないnullには使えません。

C#
object? value = null;
value.ToString(); // NullReferenceException

8-2. Convert.ToString(null)は何を返す?

Convert.ToString((object?)null)は空文字を返します。

C#
string? text = Convert.ToString((object?)null);

Console.WriteLine(text == ""); // True

ただし、string?をそのまま渡した場合は、Convert.ToString(string?)が呼ばれてnullが返る場合があります。

C#
string? value = null;
string? text = Convert.ToString(value);

nullを必ず空文字にしたいなら、次の書き方が明確です。

C#
string text = value ?? string.Empty;

8-3. ?.ToString() ?? string.Emptyは安全?

はい、安全な書き方です。

C#
string text = value?.ToString() ?? string.Empty;

valuenullの場合、value?.ToString()nullになり、その後?? string.Emptyによって空文字が返ります。

8-4. Nullable<T>.ToString()は例外になる?

int?DateTime?などのNullable型では、値がnullでもToString()は空文字を返します。

C#
int? value = null;
string text = value.ToString();

Console.WriteLine(text == ""); // True

参照型のnullに対するToString()とは挙動が異なります。

8-5. nullを"null"という文字列に変換するには?

nullの場合に"null"という文字列を返したいなら、次のように書きます。

C#
string text = value?.ToString() ?? "null";

JSONのような表現で明示的にnullと出したい場合に使えます。

ただし、null"null"は別物です。"null"は4文字の文字列なので、データとして扱う場合は注意しましょう。

8-6. 結局どの書き方を使えばよい?

多くの場面では、次の考え方で選べば問題ありません。

string?を空文字にしたい場合は、次の書き方が分かりやすいです。

C#
string text = value ?? string.Empty;

object?を安全に文字列化したい場合は、次の書き方が使いやすいです。

C#
string text = value?.ToString() ?? string.Empty;

nullの場合に表示用の文言を出したい場合は、次のようにします。

C#
string text = value?.ToString() ?? "未設定";

nullのまま保持したい場合は、次のようにします。

C#
string? text = value?.ToString();

重要なのは、nullを空文字にしたいのか、nullのまま扱いたいのか、別の文字列に置き換えたいのかを明確にすることです。

まとめ

C#では、null参照に対してToString()を呼び出すとNullReferenceExceptionが発生します。これは、ToString()nullを返すからではなく、nullにはメソッドを呼び出す対象となるオブジェクトが存在しないためです。

安全に文字列変換したい場合は、次のような書き方を使います。

C#
string text = value?.ToString() ?? string.Empty;

string?型なら、ToString()を呼ばずに次のように書くほうが自然です。

C#
string text = value ?? string.Empty;

また、Convert.ToString()は便利ですが、オーバーロードによってnullの扱いが変わる場合があるため、意図を明確にしたい場合は?.ToString() ?? string.Emptyvalue ?? string.Emptyを使うと読みやすく安全です。

実務では、nullを空文字にするのか、nullのまま保持するのか、「未設定」などの表示文字列に変換するのかを場面ごとに判断することが大切です。