C#のnullable intとは?int?の使い方・null判定・変換エラーを初心者向けに解説
はじめに
C#で数値を扱うとき、もっともよく使う型のひとつがintです。intは整数を入れるための型ですが、通常のintにはnullを代入できません。
しかし実際の開発では、「値がまだ入力されていない」「データベース上ではNULLになっている」「APIレスポンスで数値項目が省略されることがある」といった場面があります。このようなときに使うのが、nullable int、つまりint?です。
この記事では、C#のnullable intとは何か、int?の基本的な使い方、null判定、int?からintへの変換、stringからnullable intへの変換方法、よくあるエラーと安全な書き方を初心者向けに解説します。
1. C#のnullable int(int?)とは?
1-1. nullable intは「nullを入れられるint型」
C#のnullable intとは、簡単にいうと「nullを入れられるint型」です。
通常のintには整数しか代入できません。
C#int number = 10;
一方で、int?を使うと整数だけでなくnullも代入できます。
C#int? number = 10;
int? emptyNumber = null;
このint?が、C#におけるnullable intです。
nullは「値が存在しない」という意味を表します。つまりint?は、「整数が入っているかもしれないし、値がないかもしれない」状態を表現できる型です。
1-2. intとint?の違い
intとint?の大きな違いは、nullを代入できるかどうかです。
C#int a = 0; // OK
int b = null; // エラー
int? c = 0; // OK
int? d = null; // OK
intは必ず数値を持ちます。未入力や不明な値を表したい場合でも、0などの数値を入れる必要があります。
しかし、0は「値がない」という意味ではありません。たとえば年齢が0の場合、それは「0歳」という意味です。一方でnullは「年齢が未入力」「年齢が不明」という意味を表せます。
そのため、値が存在しない可能性がある整数にはint?を使うのが自然です。
1-3. int?はNullable<int>の省略記法
int?は、実はNullable<int>の省略記法です。
以下の2つは同じ意味です。
C#int? age = null;
Nullable<int> score = null;
Nullable<T>は、値型にnullを扱えるようにするための仕組みです。int、double、bool、DateTimeなどの値型は、通常そのままではnullを代入できません。
たとえば次のように書けます。
C#double? price = null;
bool? isActive = null;
DateTime? birthday = null;
int?はNullable<int>より短く読みやすいため、実務ではint?の書き方がよく使われます。
1-4. なぜintにnullを入れたい場面があるのか
プログラムでは、数値が必ず存在するとは限りません。
たとえば、次のようなケースがあります。
C#int? age = null; // 年齢が未入力
int? score = null; // テストを未受験
int? userId = null; // ユーザーIDがまだ発行されていない
このような値を通常のintで表そうとすると、仮の値として0や-1を使うことがあります。
C#int age = -1; // 未入力を表すつもり
しかし、この書き方は意味がわかりにくく、バグの原因になりやすいです。-1が本当に未入力なのか、特別な意味を持つ値なのかがコードから判断しづらいからです。
int?を使えば、「値がない」という状態をnullとして明確に表現できます。
C#int? age = null;
2. int?の基本的な使い方
2-1. int?の宣言と代入方法
int?は次のように宣言します。
C#int? number;
宣言と同時に値を代入することもできます。
C#int? number = 100;
int?には整数値またはnullを代入できます。
C#int? value1 = 10;
int? value2 = null;
通常のintと似ていますが、nullを扱える点が大きな違いです。
2-2. nullを代入する書き方
int?には、次のようにnullを代入できます。
C#int? count = null;
あとからnullを代入することも可能です。
C#int? count = 5;
count = null;
このように、値がなくなった状態や未設定の状態を表したいときにnullを使います。
たとえば、入力フォームで年齢が未入力だった場合は、次のように表現できます。
C#int? age = null;
2-3. 通常のint値を代入する書き方
int?には通常の整数値もそのまま代入できます。
C#int? age = 25;
int型の変数をint?に代入することもできます。
C#int number = 10;
int? nullableNumber = number;
この変換は暗黙的に行われるため、特別なキャストは不要です。
つまり、intからint?への変換は安全に行えます。
2-4. Nullable<int>として書く場合との違い
int?とNullable<int>は同じ意味です。
C#int? a = null;
Nullable<int> b = null;
どちらを使っても動作は同じです。
ただし、一般的にはint?のほうが短く、読みやすいためよく使われます。
C#int? age = null;
Nullable<int>と書くと、型の仕組みを明示できますが、日常的なコードでは少し長く感じられます。
C#Nullable<int> age = null;
初心者のうちは、int?はNullable<int>の省略形だと理解しておけば十分です。
3. nullable intのnull判定方法
3-1. == nullで判定する
int?がnullかどうかを調べるには、== nullを使えます。
C#int? age = null;
if (age == null)
{
Console.WriteLine("年齢は未入力です");
}
この書き方は直感的でわかりやすいため、初心者にもおすすめです。
int?に値が入っていない場合、age == nullはtrueになります。
C#int? age = null;
Console.WriteLine(age == null); // True
3-2. != nullで値があるか判定する
値が入っているかどうかを確認したい場合は、!= nullを使います。
C#int? age = 20;
if (age != null)
{
Console.WriteLine("年齢が入力されています");
}
値がある場合だけ処理したいときによく使います。
C#int? score = 80;
if (score != null)
{
Console.WriteLine($"点数は{score}点です");
}
ただし、scoreはこの時点でも型としてはint?です。通常のintとして扱いたい場合は、変換方法に注意が必要です。
3-3. HasValueで判定する
int?にはHasValueというプロパティがあります。
HasValueは、値が入っていればtrue、nullであればfalseを返します。
C#int? age = 30;
if (age.HasValue)
{
Console.WriteLine("値があります");
}
nullの場合はfalseになります。
C#int? age = null;
Console.WriteLine(age.HasValue); // False
age != nullとage.HasValueは、ほぼ同じ意味で使えます。
C#if (age != null)
{
// 値がある場合
}
if (age.HasValue)
{
// 値がある場合
}
3-4. Valueを使うときの注意点
int?に入っている値を取り出すには、Valueプロパティを使えます。
C#int? age = 25;
int actualAge = age.Value;
ただし、Valueはnullの状態で使うとエラーになります。
C#int? age = null;
int actualAge = age.Value; // エラー
このとき発生する代表的なエラーが、Nullable object must have a valueです。
そのため、Valueを使う前には必ず値があるか確認しましょう。
C#int? age = null;
if (age.HasValue)
{
int actualAge = age.Value;
Console.WriteLine(actualAge);
}
else
{
Console.WriteLine("年齢は未入力です");
}
3-5. GetValueOrDefaultでデフォルト値を取得する
GetValueOrDefaultを使うと、int?がnullの場合にデフォルト値を取得できます。
C#int? count = null;
int result = count.GetValueOrDefault();
Console.WriteLine(result); // 0
int?の場合、引数なしのGetValueOrDefault()は、nullのときに0を返します。
任意のデフォルト値を指定することもできます。
C#int? count = null;
int result = count.GetValueOrDefault(-1);
Console.WriteLine(result); // -1
nullのときに特定の値を使いたい場合に便利です。
C#int? score = null;
int displayScore = score.GetValueOrDefault(0);
ただし、nullと0は本来別の意味です。デフォルト値に置き換えてよい場面かどうかは、よく考える必要があります。
4. int?からintへ変換する方法
4-1. 明示的キャストで変換する
int?からintへ変換するには、明示的キャストを使う方法があります。
C#int? nullableNumber = 10;
int number = (int)nullableNumber;
値が入っている場合は問題なく変換できます。
しかし、nullableNumberがnullの場合はエラーになります。
C#int? nullableNumber = null;
int number = (int)nullableNumber; // エラー
そのため、明示的キャストを使う場合は、事前にnullでないことを確認する必要があります。
C#int? nullableNumber = 10;
if (nullableNumber != null)
{
int number = (int)nullableNumber;
Console.WriteLine(number);
}
4-2. Valueプロパティで変換する
Valueプロパティを使ってint?からintへ変換することもできます。
C#int? nullableNumber = 20;
int number = nullableNumber.Value;
これも値がある場合は問題ありません。
ただし、nullの場合はエラーになります。
C#int? nullableNumber = null;
int number = nullableNumber.Value; // エラー
安全に使うには、HasValueで確認してからValueを使います。
C#int? nullableNumber = 20;
if (nullableNumber.HasValue)
{
int number = nullableNumber.Value;
Console.WriteLine(number);
}
Valueは便利ですが、安易に使うと実行時エラーの原因になります。
4-3. ??演算子でnull時の値を指定する
int?からintへ安全に変換する方法として、??演算子があります。
??演算子は、左側がnullでなければその値を使い、nullであれば右側の値を使います。
C#int? nullableNumber = null;
int number = nullableNumber ?? 0;
Console.WriteLine(number); // 0
値がある場合は、その値が使われます。
C#int? nullableNumber = 15;
int number = nullableNumber ?? 0;
Console.WriteLine(number); // 15
この書き方はシンプルで安全です。
C#int? age = null;
int displayAge = age ?? -1;
nullの場合にどの値として扱うかが明確な場合は、??演算子を使うとよいでしょう。
4-4. GetValueOrDefaultで安全に変換する
GetValueOrDefaultを使っても、int?からintへ安全に変換できます。
C#int? nullableNumber = null;
int number = nullableNumber.GetValueOrDefault();
Console.WriteLine(number); // 0
任意のデフォルト値を指定することもできます。
C#int? nullableNumber = null;
int number = nullableNumber.GetValueOrDefault(100);
Console.WriteLine(number); // 100
??演算子と似た用途で使えます。
C#int number1 = nullableNumber ?? 100;
int number2 = nullableNumber.GetValueOrDefault(100);
どちらを使ってもよいですが、一般的には??演算子のほうが短く読みやすいです。
4-5. nullの可能性があるときに避けるべき変換
nullの可能性があるint?を、確認せずにintへ変換するのは避けましょう。
避けるべき例は次のとおりです。
C#int? value = null;
int number1 = (int)value;
int number2 = value.Value;
どちらもvalueがnullの場合にエラーになります。
安全に書くなら、次のようにします。
C#int? value = null;
int number = value ?? 0;
または、nullの場合は別処理にします。
C#int? value = null;
if (value.HasValue)
{
int number = value.Value;
Console.WriteLine(number);
}
else
{
Console.WriteLine("値がありません");
}
int?をintへ変換するときは、「nullだったらどうするか」を必ず考えることが重要です。
5. stringからnullable intへ変換する方法
5-1. int.Parseで変換する場合の注意点
文字列を整数に変換するには、int.Parseを使えます。
C#string text = "123";
int number = int.Parse(text);
ただし、int.Parseは変換できない文字列を渡すとエラーになります。
C#string text = "abc";
int number = int.Parse(text); // FormatException
空文字でもエラーになります。
C#string text = "";
int number = int.Parse(text); // FormatException
int.Parseは、必ず数値の文字列が入っているとわかっている場合には使えます。
しかし、入力フォームやCSVなど、どんな文字列が来るかわからない場面では注意が必要です。
5-2. int.TryParseで安全に変換する
安全に文字列を整数へ変換するには、int.TryParseを使います。
C#string text = "123";
if (int.TryParse(text, out int number))
{
Console.WriteLine($"変換成功: {number}");
}
else
{
Console.WriteLine("変換できませんでした");
}
TryParseは、変換に成功するとtrueを返し、変換後の値をout引数に入れます。
変換に失敗しても例外は発生しません。
C#string text = "abc";
bool success = int.TryParse(text, out int number);
Console.WriteLine(success); // False
ユーザー入力のように不正な値が入る可能性がある場合は、int.Parseよりint.TryParseを使うのが安全です。
5-3. 空文字やnullをint?に変換する実装例
空文字やnullをint?に変換したい場合は、次のようなメソッドを作ると便利です。
C#static int? ToNullableInt(string? text)
{
if (string.IsNullOrWhiteSpace(text))
{
return null;
}
if (int.TryParse(text, out int number))
{
return number;
}
return null;
}
使い方は次のとおりです。
C#int? value1 = ToNullableInt("123"); // 123
int? value2 = ToNullableInt(""); // null
int? value3 = ToNullableInt(null); // null
int? value4 = ToNullableInt("abc"); // null
この実装では、空文字、空白、null、数値に変換できない文字列をすべてnullとして扱っています。
不正な文字列の場合はエラーにしたい場合、次のように例外を投げる設計もあります。
C#static int? ToNullableInt(string? text)
{
if (string.IsNullOrWhiteSpace(text))
{
return null;
}
if (int.TryParse(text, out int number))
{
return number;
}
throw new FormatException("数値に変換できない文字列です");
}
仕様に応じて、nullにするのかエラーにするのかを決めましょう。
5-4. 入力フォームやCSV読み込みでよくある使い方
入力フォームでは、年齢や点数などが未入力になることがあります。
C#string? inputAge = "";
int? age = ToNullableInt(inputAge);
この場合、未入力を0ではなくnullとして扱えます。
CSV読み込みでも同じです。
C#string csvAge = ""; // 年齢列が空
string csvScore = "85"; // 点数列に値あり
int? age = ToNullableInt(csvAge);
int? score = ToNullableInt(csvScore);
結果は次のようになります。
C#age // null
score // 85
データベースに保存する場合も、nullとして扱えば「未入力」という意味を保てます。
C#if (age == null)
{
Console.WriteLine("年齢は未入力です");
}
6. nullable intでよくあるエラーと原因
6-1. Nullable object must have a valueの原因
Nullable object must have a valueは、int?がnullなのにValueを使ったときによく発生します。
C#int? age = null;
int actualAge = age.Value; // エラー
Valueは中身の値を取り出すためのプロパティですが、nullの場合は取り出す値がありません。
このエラーを防ぐには、HasValueで確認します。
C#int? age = null;
if (age.HasValue)
{
int actualAge = age.Value;
Console.WriteLine(actualAge);
}
else
{
Console.WriteLine("値がありません");
}
または、??演算子を使います。
C#int? age = null;
int actualAge = age ?? 0;
6-2. int?をintに暗黙的に変換できないエラー
次のコードはエラーになります。
C#int? nullableNumber = 10;
int number = nullableNumber; // エラー
int?にはnullが入る可能性があります。そのため、C#は自動的にintへ変換できません。
安全に変換するには、??演算子などを使います。
C#int? nullableNumber = 10;
int number = nullableNumber ?? 0;
または、値があることを確認してから変換します。
C#if (nullableNumber.HasValue)
{
int number = nullableNumber.Value;
}
intからint?への変換は自動でできますが、int?からintへの変換は注意が必要です。
C#int number = 10;
int? nullableNumber = number; // OK
逆方向は、null対策が必要です。
6-3. nullをintに代入できないエラー
通常のintにはnullを代入できません。
C#int age = null; // エラー
nullを扱いたい場合は、int?を使います。
C#int? age = null; // OK
この違いは初心者がつまずきやすいポイントです。
intは「必ず整数がある」場合に使います。
C#int count = 0;
int?は「整数がない可能性がある」場合に使います。
C#int? count = null;
6-4. Parse失敗によるFormatException
int.Parseで数値ではない文字列を変換しようとすると、FormatExceptionが発生します。
C#string text = "abc";
int number = int.Parse(text); // FormatException
空文字でも同じです。
C#string text = "";
int number = int.Parse(text); // FormatException
外部から受け取った文字列を変換する場合は、int.TryParseを使うほうが安全です。
C#string text = "abc";
if (int.TryParse(text, out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("数値ではありません");
}
TryParseを使えば、変換に失敗してもプログラムが止まりにくくなります。
6-5. エラーを防ぐ安全な書き方
nullable intのエラーを防ぐには、次の考え方が重要です。
まず、int?からintへ変換するときは、必ずnullの場合を考えます。
C#int? value = null;
int number = value ?? 0;
次に、Valueを使う場合は事前にHasValueを確認します。
C#if (value.HasValue)
{
int number = value.Value;
}
文字列から変換するときは、int.Parseよりint.TryParseを優先します。
C#string input = "123";
int? number = int.TryParse(input, out int result)
? result
: null;
また、空文字やnullを扱う場合は、先にチェックします。
C#string? input = "";
int? number = string.IsNullOrWhiteSpace(input)
? null
: int.TryParse(input, out int result) ? result : null;
安全な書き方を習慣にすると、Nullable object must have a valueやFormatExceptionなどのエラーを減らせます。
7. nullable intを使う実践例
7-1. 未入力の年齢や点数を扱う
入力フォームで年齢が未入力の場合、int?を使うと自然に表現できます。
C#int? age = null;
年齢が入力されている場合は数値を代入します。
C#age = 25;
表示するときは、nullかどうかを判定します。
C#if (age.HasValue)
{
Console.WriteLine($"年齢: {age.Value}歳");
}
else
{
Console.WriteLine("年齢は未入力です");
}
テストの点数でも同じです。
C#int? score = null;
if (score == null)
{
Console.WriteLine("未受験です");
}
else
{
Console.WriteLine($"点数: {score}点");
}
0点と未受験は意味が違います。int?を使うことで、この違いを正しく表現できます。
7-2. データベースのNULL値を扱う
データベースでは、数値カラムがNULLになることがあります。
たとえば、AgeカラムがNULL許可の場合、C#側ではint?として扱うのが自然です。
C#public class User
{
public int Id { get; set; }
public int? Age { get; set; }
}
Ageが未登録の場合はnullになります。
C#User user = new User
{
Id = 1,
Age = null
};
表示するときは、null判定を行います。
C#if (user.Age == null)
{
Console.WriteLine("年齢未登録");
}
else
{
Console.WriteLine($"{user.Age}歳");
}
データベースのNULLとC#のnullを対応させることで、データの意味を保ったまま扱えます。
7-3. APIレスポンスの省略可能な数値を扱う
APIレスポンスでは、数値項目が省略されたり、nullで返ってきたりすることがあります。
たとえば、次のようなレスポンスを考えます。
JSON{
"id": 1,
"name": "Taro",
"age": null
}
この場合、C#のモデルではAgeをint?にします。
C#public class UserResponse
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int? Age { get; set; }
}
Ageが存在しない可能性があるなら、通常のintではなくint?にすることで安全に扱えます。
C#if (response.Age.HasValue)
{
Console.WriteLine($"年齢: {response.Age.Value}");
}
else
{
Console.WriteLine("年齢情報はありません");
}
外部APIを扱うときは、値が必ず返るとは限らないため、nullable intがよく使われます。
7-4. LINQや条件分岐でint?を使う
int?はLINQや条件分岐でもよく使います。
たとえば、年齢が入力されているユーザーだけを抽出する場合です。
C#var usersWithAge = users.Where(user => user.Age.HasValue);
年齢が20歳以上のユーザーだけを抽出する場合は、次のように書けます。
C#var adults = users.Where(user => user.Age >= 20);
ただし、Ageがnullの場合、比較結果はfalseのように扱われます。明示的に書くなら次のようにできます。
C#var adults = users.Where(user => user.Age.HasValue && user.Age.Value >= 20);
nullの場合にデフォルト値を使って並び替えることもできます。
C#var orderedUsers = users.OrderBy(user => user.Age ?? int.MaxValue);
この例では、Ageがnullのユーザーを最後に並べるためにint.MaxValueを使っています。
8. nullable intを使うときの注意点
8-1. nullと0は別の意味として扱う
int?を使ううえで重要なのは、nullと0を混同しないことです。
C#int? score1 = null; // 未受験
int? score2 = 0; // 0点
この2つはまったく違う意味です。
nullは「値がない」ことを表します。0は「数値として0である」ことを表します。
年齢でも同じです。
C#int? age1 = null; // 未入力
int? age2 = 0; // 0歳
nullを安易に0へ変換すると、意味が変わってしまうことがあります。
C#int displayAge = age1 ?? 0;
この書き方が悪いわけではありませんが、「未入力」を「0歳」と表示してよいのかは確認が必要です。
8-2. 安易にValueを使わない
Valueは便利ですが、nullの場合にエラーになります。
C#int? value = null;
int number = value.Value; // エラー
そのため、Valueを使うときは必ずHasValueを確認しましょう。
C#if (value.HasValue)
{
int number = value.Value;
}
ただし、多くの場合は??演算子のほうが簡潔です。
C#int number = value ?? 0;
「値がない場合はどうするか」が明確なときは、??を使うと読みやすくなります。
8-3. null許容参照型との違いを理解する
C#には、int?のようなnullable値型とは別に、null許容参照型という仕組みもあります。
たとえば、次のような書き方です。
C#string? name = null;
int?とstring?は見た目が似ていますが、意味する仕組みは少し違います。
intは値型です。通常はnullを持てないため、Nullable<int>、つまりint?を使ってnullを扱えるようにします。
一方、stringは参照型です。string?は「この参照型はnullになる可能性がある」という注釈として使われます。
C#int? age = null; // Nullable<int>
string? name = null; // null許容参照型
初心者のうちは、int?は「nullを入れられるint」、string?は「nullの可能性を明示したstring」と理解しておくとよいでしょう。
8-4. 可読性を下げないための書き方
int?を使うと便利ですが、null判定や変換が多すぎるとコードが読みにくくなることがあります。
読みにくい例です。
C#int result = value.HasValue ? value.Value : 0;
この場合は、??演算子を使うとすっきりします。
C#int result = value ?? 0;
また、複雑な変換処理はメソッドに分けると読みやすくなります。
C#static int? ToNullableInt(string? text)
{
if (string.IsNullOrWhiteSpace(text))
{
return null;
}
return int.TryParse(text, out int number) ? number : null;
}
呼び出し側はシンプルになります。
C#int? age = ToNullableInt(input);
nullable intを使うときは、ただ動くコードを書くのではなく、「nullの意味が読み取れるか」「安全に変換できているか」を意識しましょう。
9. C#のnullable intに関するよくある質問
9-1. int?とNullable<int>はどちらを使うべき?
基本的にはint?を使うのがおすすめです。
C#int? age = null;
int?はNullable<int>の省略記法なので、動作は同じです。
C#Nullable<int> age = null;
どちらも同じ意味ですが、int?のほうが短く、一般的なC#コードでよく使われます。
ただし、学習目的で仕組みを説明するときや、ジェネリック型として明示したいときはNullable<int>と書くこともあります。
通常の開発では、読みやすさを優先してint?を使うとよいでしょう。
9-2. int?に計算や比較はできる?
int?でも計算や比較はできます。
C#int? a = 10;
int? b = 20;
int? sum = a + b;
Console.WriteLine(sum); // 30
ただし、どちらかがnullの場合、結果もnullになります。
C#int? a = 10;
int? b = null;
int? sum = a + b;
Console.WriteLine(sum); // null
比較もできます。
C#int? age = 20;
if (age >= 18)
{
Console.WriteLine("成人です");
}
ただし、ageがnullの場合、条件は成立しません。
より明確に書くなら、次のようにします。
C#if (age.HasValue && age.Value >= 18)
{
Console.WriteLine("成人です");
}
else
{
Console.WriteLine("年齢が未入力、または18歳未満です");
}
9-3. int?の初期値は何?
int?の初期値はnullです。
クラスのプロパティとして宣言した場合、明示的に代入しなければnullになります。
C#public class User
{
public int? Age { get; set; }
}
この場合、Ageの初期値はnullです。
C#User user = new User();
Console.WriteLine(user.Age == null); // True
ローカル変数の場合は、使用前に値を代入する必要があります。
C#int? age;
age = null;
Console.WriteLine(age == null);
int?は「値がない状態」を表せるため、初期値としてnullを使う場面が多いです。
9-4. nullの場合だけ別処理にするには?
nullの場合だけ別処理にしたい場合は、== nullを使うとわかりやすいです。
C#int? age = null;
if (age == null)
{
Console.WriteLine("年齢は未入力です");
}
else
{
Console.WriteLine($"年齢は{age}歳です");
}
HasValueを使うこともできます。
C#if (!age.HasValue)
{
Console.WriteLine("年齢は未入力です");
}
else
{
Console.WriteLine($"年齢は{age.Value}歳です");
}
nullの場合にデフォルト値を使うだけなら、??演算子が便利です。
C#int displayAge = age ?? 0;
ただし、nullを0として扱ってよいかどうかは、仕様に合わせて判断しましょう。
まとめ
C#のnullable intは、nullを入れられる整数型です。通常のintにはnullを代入できませんが、int?を使うことで「値があるかもしれないし、ないかもしれない」という状態を表現できます。
int?はNullable<int>の省略記法です。
C#int? age = null;
Nullable<int> score = null;
int?のnull判定には、== null、!= null、HasValueなどを使います。
C#if (age == null)
{
Console.WriteLine("未入力です");
}
if (age.HasValue)
{
Console.WriteLine(age.Value);
}
ただし、Valueはnullのときに使うとNullable object must have a valueというエラーになるため注意が必要です。
int?からintへ変換する場合は、??演算子やGetValueOrDefaultを使うと安全です。
C#int number = age ?? 0;
文字列からnullable intへ変換する場合は、int.Parseではなくint.TryParseを使うと、変換エラーを防ぎやすくなります。
C#int? number = int.TryParse(input, out int result) ? result : null;
nullable intを使うときは、nullと0を別の意味として扱うことが大切です。nullは「値がない」、0は「数値として0」です。
未入力の年齢、未受験の点数、データベースのNULL値、APIレスポンスの省略可能な数値など、値が存在しない可能性がある場面ではint?を使うと、意味が明確で安全なコードを書けます。

