C#のdefaultとは?型ごとのデフォルト値と使い方を初心者向けに解説
はじめに
C#を学び始めると、defaultというキーワードを見かけることがあります。
たとえば、次のようなコードです。
C#int number = default;
string text = default;
bool flag = default;
一見すると「何も値を入れていないように見える」かもしれません。しかし、C#では型ごとにあらかじめ決められたデフォルト値があり、defaultを使うことでその値を取得できます。
intなら0、boolならfalse、stringのような参照型ならnullになります。
この記事では、C#のdefaultとは何か、型ごとのデフォルト値、基本的な書き方、nullとの違い、実践的な使い方まで初心者向けにわかりやすく解説します。
1. C#のdefaultとは?まず押さえたい基本
1-1. defaultは「型ごとの既定値」を取得するためのキーワード
C#のdefaultは、指定した型の既定値を取得するためのキーワードです。
既定値とは、その型において「何も明示的な値を指定しなかった場合に使われる基本の値」のことです。
たとえば、int型の既定値は0です。
C#int number = default(int);
Console.WriteLine(number); // 0
このコードでは、default(int)によってint型のデフォルト値である0を取得しています。
C# 7.1以降では、型が推論できる場合にdefaultだけで書くこともできます。
C#int number = default;
Console.WriteLine(number); // 0
1-2. defaultで返る値は型によって変わる
defaultで返る値は、すべての型で同じではありません。型によって返る値が異なります。
たとえば、次のようになります。
C#int number = default; // 0
bool flag = default; // false
string text = default; // null
DateTime date = default; // 0001/01/01 00:00:00
数値型では0、bool型ではfalse、参照型ではnullになります。
つまり、defaultは「空っぽの値」を返すのではなく、「その型にとっての標準的な初期状態」を返すと考えると理解しやすいです。
1-3. 「デフォルト値」と「初期値」の違い
初心者が混乱しやすいポイントとして、「デフォルト値」と「初期値」の違いがあります。
デフォルト値は、C#の型ごとに決まっている既定の値です。
一方、初期値は、変数やフィールドを使い始めるときに最初に入っている値、または自分で設定した値を指します。
C#int a = default; // デフォルト値で初期化
int b = 10; // 10で初期化
この場合、aの初期値は0であり、それはint型のデフォルト値です。
一方、bの初期値は10ですが、これはint型のデフォルト値ではありません。
つまり、デフォルト値は「型が持つ標準の値」、初期値は「実際に最初に入っている値」と考えるとよいでしょう。
1-4. 初心者がdefaultを理解しておくべき理由
defaultは、C#の基礎を理解するうえでとても重要です。
その理由は、変数、配列、フィールド、ジェネリック、Dictionary、Nullable、nullチェックなど、さまざまな場面でデフォルト値の考え方が関係するからです。
たとえば、配列を作成した直後の要素には、自動的に型のデフォルト値が入ります。
C#int[] numbers = new int[3];
Console.WriteLine(numbers[0]); // 0
このように、自分でdefaultと書いていなくても、C#の内部ではデフォルト値の考え方が使われています。
defaultを理解しておくと、「なぜこの値になるのか」「なぜnullになるのか」といった疑問を解消しやすくなります。
2. C#の型ごとのデフォルト値一覧
2-1. 数値型のデフォルト値は0
int、long、float、double、decimalなどの数値型のデフォルト値は0です。
C#int intValue = default;
long longValue = default;
double doubleValue = default;
decimal decimalValue = default;
Console.WriteLine(intValue); // 0
Console.WriteLine(longValue); // 0
Console.WriteLine(doubleValue); // 0
Console.WriteLine(decimalValue); // 0
整数型でも浮動小数点型でも、基本的には0に相当する値がデフォルト値になります。
ただし、型によって内部的な表現は異なります。たとえば、doubleでは0.0、decimalでは0mのように扱われます。
2-2. bool型のデフォルト値はfalse
bool型のデフォルト値はfalseです。
C#bool isActive = default;
Console.WriteLine(isActive); // false
bool型はtrueまたはfalseのどちらかを表します。
そのうち、C#ではfalseがデフォルト値として扱われます。
フラグを表す変数や、条件判定に使う変数を初期化する場合、この性質を知っておくと便利です。
C#bool isCompleted = default;
if (!isCompleted)
{
Console.WriteLine("まだ完了していません。");
}
2-3. char型のデフォルト値は'\0'
char型のデフォルト値は'\0'です。
C#char c = default;
Console.WriteLine(c);
'\0'はヌル文字と呼ばれる文字です。見た目として画面に表示される文字ではないため、Console.WriteLineで出力しても何も表示されていないように見えることがあります。
空文字""やスペース' 'とは別物です。
C#char defaultChar = default;
char spaceChar = ' ';
Console.WriteLine(defaultChar == '\0'); // true
Console.WriteLine(spaceChar == '\0'); // false
charのデフォルト値は、空白文字ではなくヌル文字である点に注意しましょう。
2-4. enum型のデフォルト値は0に対応する値
enum型のデフォルト値は、数値として0に対応する値です。
C#enum Status
{
None = 0,
Active = 1,
Completed = 2
}
Status status = default;
Console.WriteLine(status); // None
この例では、Noneが0に対応しているため、defaultはStatus.Noneになります。
ただし、0に対応する名前を定義していない場合でも、デフォルト値は数値として0になります。
C#enum Color
{
Red = 1,
Blue = 2,
Green = 3
}
Color color = default;
Console.WriteLine(color); // 0
このように、enumでは0に対応する値が存在しないと、想定外の状態になることがあります。
そのため、enumを定義するときは、None = 0やUnknown = 0のような値を用意しておくと安全です。
2-5. 参照型のデフォルト値はnull
string、クラス、配列、インターフェイス、デリゲートなどの参照型のデフォルト値はnullです。
C#string name = default;
Console.WriteLine(name == null); // true
stringは文字列を扱う型ですが、参照型です。そのため、デフォルト値は空文字""ではなくnullになります。
C#string text1 = default;
string text2 = "";
Console.WriteLine(text1 == null); // true
Console.WriteLine(text2 == null); // false
nullは「インスタンスを参照していない状態」を表します。
そのため、defaultで参照型を初期化したあとに、何もチェックせずメソッドやプロパティを呼び出すと例外が発生することがあります。
2-6. Nullable型のデフォルト値はnull
int?やDateTime?のようなNullable型のデフォルト値はnullです。
Nullable型は、値型にnullを許可するための型です。
C#int? number = default;
DateTime? date = default;
Console.WriteLine(number == null); // true
Console.WriteLine(date == null); // true
通常のintはnullを持てません。
C#int number = null; // エラー
しかし、int?のようにNullable型にすると、nullを持てます。
C#int? number = null; // OK
Nullable型のdefaultは、「値が存在しない状態」を表すnullになります。
2-7. 構造体のデフォルト値は各フィールドのdefault
構造体のデフォルト値は、各フィールドがそれぞれの型のデフォルト値になった状態です。
C#struct User
{
public int Id;
public string Name;
public bool IsActive;
}
User user = default;
Console.WriteLine(user.Id); // 0
Console.WriteLine(user.Name); // null
Console.WriteLine(user.IsActive); // false
この例では、Idはintなので0、Nameはstringなのでnull、IsActiveはboolなのでfalseになります。
構造体全体に特別な「空の値」があるわけではなく、フィールドごとにデフォルト値が設定されると考えるとわかりやすいです。
3. defaultの基本的な書き方
3-1. default(T)の使い方
default(T)は、指定した型Tのデフォルト値を取得する書き方です。
C#int number = default(int);
bool flag = default(bool);
string text = default(string);
Console.WriteLine(number); // 0
Console.WriteLine(flag); // false
Console.WriteLine(text == null); // true
default(T)のよい点は、どの型のデフォルト値を取得しているのかが明確にわかることです。
特に、ジェネリック型を扱うときによく使われます。
C#T GetDefaultValue<T>()
{
return default(T);
}
このように、型Tが実行時まで具体的に決まらない場合でも、default(T)を使えばその型に応じたデフォルト値を返せます。
3-2. defaultリテラルの使い方
C# 7.1以降では、型が明確にわかる場面でdefaultだけを書くことができます。
これをdefaultリテラルと呼びます。
C#int number = default;
bool flag = default;
string text = default;
左辺の型から、defaultが何型のデフォルト値なのかをコンパイラが判断します。
C#int number = default; // intのdefault
この場合、左辺がintなので、defaultはint型のデフォルト値である0になります。
メソッドの戻り値でも使えます。
C#int GetNumber()
{
return default;
}
戻り値の型がintなので、defaultは0として扱われます。
3-3. default(T)とdefaultの違い
default(T)とdefaultは、どちらも型のデフォルト値を取得するために使います。
違いは、型を明示するかどうかです。
C#int a = default(int);
int b = default;
この2つは、どちらも0になります。
default(T)は型が明示されているため、読み手にとってわかりやすい場合があります。
一方、defaultはコードを短く書けるため、型が明らかな場面では便利です。
C#string name = default; // string型だとすぐわかる
ただし、型が読み取りにくい場面では、default(T)を使ったほうが親切です。
C#var value = GetValueOrDefault(default(int));
コードの読みやすさを考えて使い分けることが大切です。
3-4. varとdefaultを組み合わせるとエラーになる理由
次のコードはエラーになります。
C#var value = default; // エラー
なぜなら、varは右辺から型を推論する仕組みだからです。
しかし、右辺のdefaultだけでは、何型のデフォルト値なのか判断できません。
intなのか、stringなのか、boolなのかがわからないため、コンパイラは型を決められません。
この場合は、型を明示する必要があります。
C#int value1 = default; // OK
var value2 = default(int); // OK
varを使いたい場合は、default(int)のように型を明示しましょう。
3-5. 具体的なコード例で確認する
実際にいくつかの型でdefaultを確認してみましょう。
C#using System;
class Program
{
static void Main()
{
int number = default;
bool flag = default;
char character = default;
string text = default;
DateTime date = default;
Console.WriteLine(number); // 0
Console.WriteLine(flag); // False
Console.WriteLine(character == '\0'); // True
Console.WriteLine(text == null); // True
Console.WriteLine(date); // 0001/01/01 0:00:00
}
}
このように、defaultの結果は型によって変わります。
初心者のうちは、「値型は何らかの値になる」「参照型は基本的にnullになる」と覚えておくと理解しやすいです。
4. defaultが使われる主な場面
4-1. 変数を型のデフォルト値で初期化したいとき
defaultは、変数をその型のデフォルト値で初期化したいときに使えます。
C#int count = default;
bool isFinished = default;
string message = default;
ただし、単純な型の場合は、直接値を書いたほうがわかりやすい場合もあります。
C#int count = 0;
bool isFinished = false;
string message = null;
defaultを使うと「型のデフォルト値を使っている」という意図を表せます。
一方で、0やfalseと書いたほうが直感的な場面もあります。
そのため、必ずdefaultを使うべきというわけではありません。
4-2. ジェネリック型Tの初期値を扱いたいとき
defaultが特に役立つのは、ジェネリック型を扱う場面です。
ジェネリックでは、型Tがintなのか、stringなのか、独自クラスなのかが事前に決まりません。
C#T GetDefault<T>()
{
return default;
}
このメソッドでは、Tに応じたデフォルト値を返します。
C#Console.WriteLine(GetDefault<int>()); // 0
Console.WriteLine(GetDefault<bool>()); // False
Console.WriteLine(GetDefault<string>() == null); // True
ジェネリックでは具体的な型がわからないため、0やnullを直接書くことができない場面があります。
そのようなとき、defaultを使うことで型に応じた安全な値を返せます。
4-3. メソッドの戻り値としてデフォルト値を返したいとき
条件に合う値が見つからなかった場合などに、メソッドの戻り値としてdefaultを返すことがあります。
C#int FindNumber(bool found)
{
if (found)
{
return 100;
}
return default;
}
この場合、戻り値の型はintなので、defaultは0になります。
ジェネリックメソッドでもよく使われます。
C#T FindValue<T>(bool found, T value)
{
if (found)
{
return value;
}
return default;
}
このコードでは、値が見つかった場合はvalueを返し、見つからなかった場合は型Tのデフォルト値を返します。
ただし、defaultを返すと「本当に見つからなかったのか」「たまたまデフォルト値が正しい値なのか」が区別しにくくなることがあります。
たとえば、intで0を返した場合、それが「見つからなかった」という意味なのか、実際の値が0だったのか判断できません。
そのような場合は、boolと組み合わせる、Nullable型を使う、例外を使うなどの設計を検討しましょう。
4-4. 配列やフィールドが自動的にデフォルト値になるケース
C#では、配列の要素やクラスのフィールドは、自動的にデフォルト値で初期化されます。
C#int[] numbers = new int[3];
Console.WriteLine(numbers[0]); // 0
Console.WriteLine(numbers[1]); // 0
Console.WriteLine(numbers[2]); // 0
int配列を作成した直後は、各要素に0が入っています。
参照型の配列では、各要素がnullになります。
C#string[] names = new string[3];
Console.WriteLine(names[0] == null); // true
また、クラスのフィールドも明示的に値を入れなければデフォルト値になります。
C#class User
{
public int Id;
public string Name;
}
User user = new User();
Console.WriteLine(user.Id); // 0
Console.WriteLine(user.Name == null); // true
このように、defaultと書かなくても、C#では多くの場面でデフォルト値が自動的に使われています。
4-5. TryGetValueなどでdefaultが使われる例
DictionaryのTryGetValueでは、キーが見つからなかった場合、out引数に値の型のデフォルト値が入ります。
C#var scores = new Dictionary<string, int>
{
{ "Alice", 90 },
{ "Bob", 80 }
};
bool found = scores.TryGetValue("Charlie", out int score);
Console.WriteLine(found); // False
Console.WriteLine(score); // 0
この例では、Charlieというキーは存在しません。そのため、foundはfalseになり、scoreにはintのデフォルト値である0が入ります。
重要なのは、scoreが0だからといって「値が見つかった」と判断してはいけないことです。
必ずTryGetValueの戻り値であるfoundを確認しましょう。
C#if (scores.TryGetValue("Alice", out int aliceScore))
{
Console.WriteLine($"スコアは{aliceScore}です。");
}
else
{
Console.WriteLine("スコアが見つかりませんでした。");
}
5. defaultとnullの違い
5-1. 参照型ではdefaultとnullが同じになる
参照型では、defaultはnullになります。
C#string text = default;
Console.WriteLine(text == null); // true
クラス型でも同じです。
C#class User
{
public string Name { get; set; }
}
User user = default;
Console.WriteLine(user == null); // true
参照型のdefaultは「どのインスタンスも参照していない状態」です。
そのため、次のようにプロパティへアクセスすると例外が発生します。
C#User user = default;
Console.WriteLine(user.Name); // NullReferenceException
参照型でdefaultを使う場合は、nullチェックを忘れないようにしましょう。
5-2. 値型ではdefaultとnullは同じではない
値型では、defaultとnullは同じではありません。
C#int number = default;
Console.WriteLine(number); // 0
intのdefaultは0です。nullではありません。
通常の値型には必ず何らかの値が入ります。そのため、次のコードはエラーになります。
C#int number = null; // エラー
boolも同じです。
C#bool flag = default;
Console.WriteLine(flag); // False
値型では、defaultはその型の既定値を表し、nullとは別物だと覚えておきましょう。
5-3. Nullable型ではdefaultがnullになる
Nullable型では、defaultはnullになります。
C#int? number = default;
Console.WriteLine(number == null); // true
int?は、intにnullを許可した型です。
通常のintではdefaultが0になりますが、int?ではdefaultがnullになります。
C#int normalNumber = default;
int? nullableNumber = default;
Console.WriteLine(normalNumber); // 0
Console.WriteLine(nullableNumber == null); // true
この違いはとても重要です。
Nullable型を使うと、「値がない状態」と「値が0である状態」を区別できます。
C#int? score = null;
if (score == null)
{
Console.WriteLine("スコアは未設定です。");
}
5-4. null許容参照型とdefaultの注意点
C# 8.0以降では、null許容参照型という機能があります。
この機能を有効にすると、stringとstring?を区別して、nullになる可能性をコード上で表現できます。
C#string name = "Alice";
string? optionalName = null;
この状態で、非nullableな参照型にdefaultを代入すると警告が出ることがあります。
C#string name = default; // 警告が出る可能性がある
stringは「nullではない文字列」として扱いたい型なのに、defaultはnullになるためです。
この場合は、意図に応じて次のように書き分けます。
C#string name = "";
string? optionalName = default;
nullを許可したいならstring?、空文字で初期化したいなら""を使うと、コードの意図が明確になります。
5-5. default!の意味と使いどころ
default!は、defaultにnull免除演算子!を付けた書き方です。
C#string name = default!;
これは、「実際にはnullかもしれないが、コンパイラの警告を抑制する」という意味になります。
たとえば、あとから必ず値が設定されるプロパティで使われることがあります。
C#class User
{
public string Name { get; set; } = default!;
}
このコードでは、Nameは非nullableなstringですが、初期値としてdefault!を設定しています。
ただし、default!を使っても実行時の値が安全になるわけではありません。実際にはnullが入る可能性があります。
そのため、初心者のうちは安易に使わないほうがよいでしょう。
default!は「警告を消すためのもの」であり、「nullを安全な値に変換するもの」ではありません。
6. defaultとデフォルト引数の違い
6-1. defaultキーワードとデフォルト引数は別物
C#には、defaultキーワードとは別に「デフォルト引数」という機能があります。
名前が似ているため混同しやすいですが、意味は異なります。
defaultキーワードは、型のデフォルト値を取得するために使います。
C#int number = default;
一方、デフォルト引数は、メソッド呼び出し時に引数を省略した場合の値を指定する機能です。
C#void ShowMessage(string message = "こんにちは")
{
Console.WriteLine(message);
}
このように、defaultキーワードとデフォルト引数は別の機能です。
6-2. デフォルト引数の基本的な書き方
デフォルト引数は、メソッドの引数に=で値を指定して定義します。
C#void Greet(string name = "ゲスト")
{
Console.WriteLine($"こんにちは、{name}さん");
}
このメソッドは、引数を指定しても、省略しても呼び出せます。
C#Greet("Alice"); // こんにちは、Aliceさん
Greet(); // こんにちは、ゲストさん
引数を省略した場合、定義時に指定した値が使われます。
数値やboolでも使えます。
C#void PrintCount(int count = 0)
{
Console.WriteLine(count);
}
6-3. 引数にdefaultを指定できるケース
メソッド呼び出し時に、引数としてdefaultを指定することもできます。
C#void PrintNumber(int number)
{
Console.WriteLine(number);
}
PrintNumber(default); // 0
この場合、PrintNumberの引数はintなので、defaultはintのデフォルト値である0になります。
参照型の引数でも使えます。
C#void PrintText(string text)
{
Console.WriteLine(text == null ? "nullです" : text);
}
PrintText(default); // nullです
ただし、読みやすさを考えると、nullを渡したい場合はnullと書いたほうが意図が伝わりやすいこともあります。
C#PrintText(null);
6-4. 混同しやすいポイントをコードで比較
defaultキーワードとデフォルト引数をコードで比較してみましょう。
C#void Show(int number = 10)
{
Console.WriteLine(number);
}
Show(); // 10
Show(default); // 0
この例では、Show()と呼び出した場合は、デフォルト引数の10が使われます。
一方、Show(default)と呼び出した場合は、int型のデフォルト値である0が渡されます。
つまり、次の2つは同じではありません。
C#Show(); // 引数を省略している
Show(default); // default値を明示的に渡している
この違いは、初心者が間違えやすいポイントです。
デフォルト引数は「省略されたときの値」、defaultは「型の既定値」と覚えておきましょう。
7. defaultを使うときの注意点
7-1. 参照型ではNullReferenceExceptionに注意する
参照型のdefaultはnullです。
そのため、defaultで初期化した参照型の変数に対して、すぐにメソッドやプロパティを呼び出すとNullReferenceExceptionが発生する可能性があります。
C#string text = default;
Console.WriteLine(text.Length); // NullReferenceException
安全に扱うには、nullチェックを行います。
C#string text = default;
if (text != null)
{
Console.WriteLine(text.Length);
}
else
{
Console.WriteLine("textはnullです。");
}
また、null条件演算子?.を使うこともできます。
C#string text = default;
Console.WriteLine(text?.Length);
参照型でdefaultを使う場合は、「nullになる可能性がある」と意識しましょう。
7-2. enumでは想定外の値になる場合がある
enumのデフォルト値は、数値として0に対応する値です。
しかし、0に対応するメンバーを定義していない場合、名前のない0が入ることがあります。
C#enum OrderStatus
{
Pending = 1,
Shipped = 2,
Delivered = 3
}
OrderStatus status = default;
Console.WriteLine(status); // 0
この状態は、意図しない値として扱われる可能性があります。
そのため、enumでは次のように0の値を明示的に定義しておくのがおすすめです。
C#enum OrderStatus
{
None = 0,
Pending = 1,
Shipped = 2,
Delivered = 3
}
こうしておけば、defaultの状態にも意味を持たせることができます。
7-3. DateTimeのdefaultは現在日時ではない
DateTimeのdefaultは、現在日時ではありません。
C#DateTime date = default;
Console.WriteLine(date);
DateTimeのデフォルト値は、0001年1月1日 00:00:00を表します。
現在日時を取得したい場合は、DateTime.NowやDateTime.UtcNowを使います。
C#DateTime now = DateTime.Now;
DateTime utcNow = DateTime.UtcNow;
次の2つはまったく意味が異なります。
C#DateTime date1 = default; // 0001/01/01 00:00:00
DateTime date2 = DateTime.Now; // 現在日時
初心者のうちは、default(DateTime)を「今の日時」と勘違いしないように注意しましょう。
7-4. 構造体のdefaultはコンストラクタとは異なる場合がある
構造体のdefaultは、基本的に各フィールドがデフォルト値になった状態です。
C#struct Point
{
public int X;
public int Y;
}
Point p = default;
Console.WriteLine(p.X); // 0
Console.WriteLine(p.Y); // 0
一方、構造体にコンストラクタがある場合、newで生成したときの処理と、defaultで得られる値の意味が異なることがあります。
C#struct Sample
{
public int Value;
public Sample(int value)
{
Value = value;
}
}
Sample a = new Sample(10);
Sample b = default;
Console.WriteLine(a.Value); // 10
Console.WriteLine(b.Value); // 0
defaultは「任意のコンストラクタで設定した特別な値」ではなく、「型の既定状態」を表します。
構造体を設計するときは、すべてのフィールドがデフォルト値になった状態でも問題がないかを考えることが大切です。
7-5. 読みやすさを考えてdefault(T)とdefaultを使い分ける
defaultは便利ですが、使いすぎるとコードの意図がわかりにくくなることがあります。
たとえば、次のコードは短く書けます。
C#int count = default;
しかし、初心者やチームメンバーにとっては、次のように書いたほうが直感的な場合もあります。
C#int count = 0;
参照型でも同じです。
C#string name = default;
この場合、defaultはnullですが、意図としてnullを入れたいなら次のように書くほうがわかりやすいこともあります。
C#string name = null;
一方で、ジェネリックのように型が不明な場合は、defaultが適しています。
C#T value = default;
つまり、型が明確で直接値を書いたほうがわかりやすい場合は0やnullを使い、型に依存した既定値を表したい場合はdefaultを使うとよいでしょう。
8. defaultを使った実践コード例
8-1. int・bool・stringでdefaultを比較する
まずは基本的な型でdefaultの違いを確認しましょう。
C#using System;
class Program
{
static void Main()
{
int number = default;
bool flag = default;
string text = default;
Console.WriteLine($"intのdefault: {number}");
Console.WriteLine($"boolのdefault: {flag}");
Console.WriteLine($"stringのdefaultはnullか: {text == null}");
}
}
実行結果は次のようになります。
C#intのdefault: 0
boolのdefault: False
stringのdefaultはnullか: True
この例から、値型と参照型でdefaultの結果が異なることがわかります。
intやboolのような値型では具体的な値になりますが、stringのような参照型ではnullになります。
8-2. ジェネリックメソッドでdefaultを使う例
次に、ジェネリックメソッドでdefaultを使う例です。
C#using System;
class Program
{
static T GetDefaultValue<T>()
{
return default;
}
static void Main()
{
int number = GetDefaultValue<int>();
bool flag = GetDefaultValue<bool>();
string text = GetDefaultValue<string>();
Console.WriteLine(number); // 0
Console.WriteLine(flag); // False
Console.WriteLine(text == null); // True
}
}
GetDefaultValue<T>は、指定された型Tのデフォルト値を返します。
Tがintなら0、boolならfalse、stringならnullになります。
ジェネリックでは型が固定されていないため、defaultを使う場面が多くなります。
8-3. Dictionaryの値取得でdefaultを扱う例
Dictionaryから値を取得するときにも、デフォルト値に注意が必要です。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var prices = new Dictionary<string, int>
{
{ "Apple", 150 },
{ "Banana", 100 }
};
if (prices.TryGetValue("Orange", out int price))
{
Console.WriteLine($"価格は{price}円です。");
}
else
{
Console.WriteLine("商品が見つかりませんでした。");
Console.WriteLine($"priceの値は{price}です。");
}
}
}
Orangeというキーは存在しないため、TryGetValueはfalseを返します。
このとき、priceにはintのデフォルト値である0が入ります。
ただし、0だからといって必ず「見つからなかった」と判断してはいけません。
商品価格が実際に0のケースも考えられるため、必ずTryGetValueの戻り値を確認しましょう。
8-4. nullチェックと組み合わせる例
参照型でdefaultを使う場合は、nullチェックと組み合わせるのが基本です。
C#using System;
class Program
{
static void Main()
{
string message = default;
if (message == null)
{
Console.WriteLine("messageはnullです。");
}
else
{
Console.WriteLine(message.Length);
}
}
}
null条件演算子を使うと、より簡潔に書けます。
C#string message = default;
int? length = message?.Length;
Console.WriteLine(length == null ? "長さを取得できません" : length.ToString());
message?.Lengthは、messageがnullでなければLengthを返し、nullなら結果もnullになります。
参照型のdefaultを扱う場合は、常にnullの可能性を考えましょう。
8-5. 初心者が真似しやすいサンプルコード
最後に、初心者が動かして確認しやすいサンプルコードを紹介します。
C#using System;
class Program
{
static void Main()
{
ShowDefault<int>();
ShowDefault<bool>();
ShowDefault<string>();
ShowDefault<DateTime>();
}
static void ShowDefault<T>()
{
T value = default;
Console.WriteLine($"{typeof(T).Name} の default: {FormatValue(value)}");
}
static string FormatValue<T>(T value)
{
if (value == null)
{
return "null";
}
return value.ToString();
}
}
このコードでは、ジェネリックメソッドを使って複数の型のデフォルト値を表示しています。
intなら0、boolならFalse、stringならnull、DateTimeなら0001/01/01 0:00:00のような値が確認できます。
defaultを理解するには、実際に複数の型で試してみるのが効果的です。
9. defaultに関するよくある疑問
9-1. intのdefaultはなぜ0なのか
intは値型であり、整数を表す型です。
C#では、値型のデフォルト値はすべてのビットがゼロになった状態を基本として扱います。
そのため、intのデフォルト値は0になります。
C#int number = default;
Console.WriteLine(number); // 0
intはnullを持つことができません。
そのため、「値がない」という状態ではなく、整数としての既定値である0が入ります。
値が未設定であることを表したい場合は、int?を使うとよいでしょう。
C#int? number = default;
Console.WriteLine(number == null); // true
9-2. stringのdefaultは空文字ではなくnullなのか
stringのデフォルト値は空文字""ではなくnullです。
理由は、stringが参照型だからです。
C#string text = default;
Console.WriteLine(text == null); // true
空文字""は、「文字数が0の文字列インスタンス」です。
一方、nullは「何も参照していない状態」です。
C#string text1 = null;
string text2 = "";
Console.WriteLine(text1 == null); // true
Console.WriteLine(text2 == null); // false
Console.WriteLine(text2.Length); // 0
つまり、nullと空文字はまったく別の状態です。
default(string)は参照型のデフォルト値なので、空文字ではなくnullになります。
9-3. DateTimeのdefaultは何を表すのか
DateTimeのdefaultは、DateTime.MinValueと同じ値です。
C#DateTime date = default;
Console.WriteLine(date == DateTime.MinValue); // True
これは、0001年1月1日 00:00:00を表します。
現在日時ではありません。
C#DateTime defaultDate = default;
DateTime now = DateTime.Now;
Console.WriteLine(defaultDate);
Console.WriteLine(now);
DateTimeで「未設定」を表したい場合、default(DateTime)を使うこともありますが、意図が曖昧になることがあります。
未設定を明確に表したい場合は、DateTime?を使うのがおすすめです。
C#DateTime? date = null;
これなら、「日付が存在しない状態」を自然に表現できます。
9-4. defaultはいつ使うべきで、いつ避けるべきか
defaultは、型に応じた既定値を扱いたいときに便利です。
特に、次のような場面では使いやすいです。
C#T value = default;
ジェネリックでは型Tが何になるかわからないため、defaultが役立ちます。
また、戻り値として型のデフォルト値を返したい場合にも使えます。
C#T FindOrDefault<T>(bool found, T value)
{
return found ? value : default;
}
一方で、具体的な型が明らかで、0やnullと書いたほうが意図が伝わる場合は、defaultを避けてもよいでしょう。
C#int count = 0;
string? name = null;
defaultは便利ですが、コードの読みやすさを優先することが大切です。
「型のデフォルト値であること」を強調したい場合はdefault、具体的な値の意味を伝えたい場合は0やnullを使うとよいでしょう。
9-5. defaultとnewの違いは何か
defaultとnewは似ているように見える場面がありますが、意味は異なります。
defaultは、型のデフォルト値を取得します。
C#int number = default; // 0
newは、新しいインスタンスを作成します。
C#var user = new User();
クラスの場合、defaultはnullになります。
C#User user1 = default;
User user2 = new User();
Console.WriteLine(user1 == null); // true
Console.WriteLine(user2 == null); // false
user1はインスタンスを参照していません。
一方、user2はnew User()によって新しいインスタンスを作成しています。
構造体の場合は、defaultとnewが似た結果になることがあります。
C#DateTime date1 = default;
DateTime date2 = new DateTime();
Console.WriteLine(date1 == date2); // true
ただし、クラスではdefaultとnewの違いが非常に大きいです。
defaultは「既定値」、newは「新しいインスタンスの作成」と覚えておきましょう。
まとめ
C#のdefaultは、型ごとのデフォルト値を取得するためのキーワードです。
intなどの数値型では0、boolではfalse、charでは'\0'、参照型ではnull、Nullable型ではnullになります。
C#int number = default; // 0
bool flag = default; // false
string text = default; // null
int? nullable = default; // null
default(T)のように型を明示する書き方と、defaultだけを書くdefaultリテラルがあります。
C#int a = default(int);
int b = default;
どちらも同じ結果になりますが、型が読み取りにくい場面ではdefault(T)を使うとわかりやすくなります。
defaultは、ジェネリック、配列、フィールド、メソッドの戻り値、TryGetValueなど、さまざまな場面で登場します。
ただし、参照型ではnullになるため、NullReferenceExceptionに注意が必要です。
また、DateTimeのdefaultは現在日時ではなく、0001年1月1日 00:00:00です。enumでは0に対応する値になるため、None = 0のような値を定義しておくと安全です。
defaultは便利なキーワードですが、常に使えばよいわけではありません。
具体的な値を書いたほうが読みやすい場合は、0、false、nullなどを直接書いても問題ありません。
大切なのは、defaultが「型ごとの既定値」を表すことを理解し、コードの意図が伝わりやすい形で使い分けることです。

